summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Botelho <renato@netgate.com>2016-11-02 10:45:19 -0200
committerRenato Botelho <renato@netgate.com>2016-11-02 10:45:19 -0200
commit841f35badba9e12f94b576f843daf49955da85fa (patch)
tree637fcf5764747ea0ed464f94cb59da330f03d629
parent02fa2d6083daaf327638f8e0fb9aa0be9bff743a (diff)
parent0f6aead99b2a420a730d47a074145dcb7d0f6721 (diff)
downloadFreeBSD-src-841f35badba9e12f94b576f843daf49955da85fa.zip
FreeBSD-src-841f35badba9e12f94b576f843daf49955da85fa.tar.gz
Merge remote-tracking branch 'origin/stable/11' into devel-11
-rw-r--r--Makefile.inc12
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c21
-rw-r--r--contrib/libarchive/NEWS3
-rw-r--r--contrib/libarchive/cat/test/main.c47
-rw-r--r--contrib/libarchive/cat/test/test.h9
-rw-r--r--contrib/libarchive/cpio/test/main.c47
-rw-r--r--contrib/libarchive/cpio/test/test.h9
-rw-r--r--contrib/libarchive/libarchive/archive.h4
-rw-r--r--contrib/libarchive/libarchive/archive_entry.h2
-rw-r--r--contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c1
-rw-r--r--contrib/libarchive/libarchive/archive_read_disk_set_standard_lookup.c2
-rw-r--r--contrib/libarchive/libarchive/test/main.c92
-rw-r--r--contrib/libarchive/libarchive/test/test.h9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_mtree_crash747.c5
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_set_format.c31
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_iso9660.c203
-rw-r--r--contrib/libarchive/tar/test/main.c40
-rw-r--r--contrib/libarchive/tar/test/test.h6
-rw-r--r--contrib/libarchive/tar/test/test_missing_file.c6
-rw-r--r--contrib/libarchive/tar/test/test_option_b.c2
-rw-r--r--contrib/libarchive/tar/test/test_symlink_dir.c2
-rw-r--r--contrib/libucl/CMakeLists.txt3
-rw-r--r--contrib/libucl/Makefile.unix9
-rw-r--r--contrib/libucl/Makefile.w325
-rw-r--r--contrib/libucl/README.md30
-rw-r--r--contrib/libucl/haskell/hucl.hs123
-rw-r--r--contrib/libucl/include/ucl++.h228
-rw-r--r--contrib/libucl/include/ucl.h16
-rw-r--r--contrib/libucl/m4/gcov.m489
-rw-r--r--contrib/libucl/python/setup.py54
-rw-r--r--contrib/libucl/python/src/uclmodule.c97
-rwxr-xr-xcontrib/libucl/python/test.sh6
-rwxr-xr-xcontrib/libucl/python/test_uclmodule.py148
-rw-r--r--contrib/libucl/python/tests/__init__.py0
-rw-r--r--contrib/libucl/python/tests/compat.py8
-rw-r--r--contrib/libucl/python/tests/test_dump.py66
-rw-r--r--contrib/libucl/python/tests/test_load.py107
-rw-r--r--contrib/libucl/python/tests/test_validation.py50
-rw-r--r--contrib/libucl/src/ucl_parser.c14
-rw-r--r--contrib/libucl/src/ucl_schema.c30
-rw-r--r--contrib/libucl/src/ucl_util.c25
-rw-r--r--contrib/libucl/tests/schema/patternProperties.json5
-rw-r--r--contrib/libucl/tests/schema/refRemote.json2
-rw-r--r--contrib/mdocml/INSTALL8
-rw-r--r--contrib/mdocml/LICENSE4
-rw-r--r--contrib/mdocml/Makefile30
-rw-r--r--contrib/mdocml/NEWS135
-rw-r--r--contrib/mdocml/TODO12
-rw-r--r--contrib/mdocml/cgi.c487
-rw-r--r--contrib/mdocml/cgi.h.example3
-rwxr-xr-xcontrib/mdocml/configure70
-rw-r--r--contrib/mdocml/configure.local.example60
-rw-r--r--contrib/mdocml/demandoc.c3
-rw-r--r--contrib/mdocml/libmandoc.h3
-rw-r--r--contrib/mdocml/main.c48
-rw-r--r--contrib/mdocml/main.h4
-rw-r--r--contrib/mdocml/man.138
-rw-r--r--contrib/mdocml/man.cgi.3287
-rw-r--r--contrib/mdocml/man.cgi.8146
-rw-r--r--contrib/mdocml/mandoc.3185
-rw-r--r--contrib/mdocml/mandoc.css5
-rw-r--r--contrib/mdocml/mandoc.db.55
-rw-r--r--contrib/mdocml/mandoc_headers.3176
-rw-r--r--contrib/mdocml/mandoc_malloc.326
-rw-r--r--contrib/mdocml/mandocdb.c15
-rw-r--r--contrib/mdocml/manpage.c3
-rw-r--r--contrib/mdocml/manpath.c11
-rw-r--r--contrib/mdocml/mansearch.c3
-rw-r--r--contrib/mdocml/mchars_alloc.37
-rw-r--r--contrib/mdocml/read.c4
-rw-r--r--contrib/mdocml/tag.c26
-rw-r--r--contrib/mdocml/term.c4
-rw-r--r--contrib/mdocml/term_ascii.c13
-rw-r--r--contrib/mdocml/test-rewb-bsd.c1
-rw-r--r--contrib/mdocml/test-rewb-sysv.c1
-rw-r--r--contrib/top/commands.c1
-rw-r--r--contrib/top/machine.h5
-rw-r--r--contrib/top/top.c23
-rw-r--r--contrib/top/top.xs25
-rw-r--r--contrib/tzdata/asia80
-rw-r--r--contrib/tzdata/australasia8
-rw-r--r--contrib/tzdata/europe44
-rw-r--r--contrib/tzdata/northamerica28
-rw-r--r--contrib/unbound/Makefile.in130
-rw-r--r--contrib/unbound/acx_nlnetlabs.m447
-rw-r--r--contrib/unbound/acx_python.m42
-rw-r--r--contrib/unbound/cachedb/cachedb.c702
-rw-r--r--contrib/unbound/cachedb/cachedb.h110
-rw-r--r--contrib/unbound/compat/arc4random.c3
-rw-r--r--contrib/unbound/compat/explicit_bzero.c4
-rw-r--r--contrib/unbound/compat/getentropy_linux.c9
-rw-r--r--contrib/unbound/compat/strsep.c65
-rw-r--r--contrib/unbound/config.h81
-rw-r--r--contrib/unbound/config.h.in75
-rwxr-xr-xcontrib/unbound/configure399
-rw-r--r--contrib/unbound/configure.ac152
-rw-r--r--contrib/unbound/contrib/README31
-rw-r--r--contrib/unbound/contrib/aaaa-filter-iterator.patch413
-rwxr-xr-xcontrib/unbound/contrib/build-unbound-localzone-from-hosts.pl67
-rw-r--r--contrib/unbound/contrib/create_unbound_ad_servers.cmd33
-rwxr-xr-xcontrib/unbound/contrib/create_unbound_ad_servers.sh39
-rw-r--r--contrib/unbound/contrib/libunbound.pc.in13
-rwxr-xr-xcontrib/unbound/contrib/parseunbound.pl140
-rw-r--r--contrib/unbound/contrib/patch_rsamd5_enable.diff22
-rwxr-xr-xcontrib/unbound/contrib/rc_d_unbound25
-rw-r--r--contrib/unbound/contrib/selinux/unbound.fc4
-rw-r--r--contrib/unbound/contrib/selinux/unbound.te42
-rw-r--r--contrib/unbound/contrib/unbound-host.nagios.patch134
-rw-r--r--contrib/unbound/contrib/unbound.init139
-rw-r--r--contrib/unbound/contrib/unbound.init_fedora119
-rw-r--r--contrib/unbound/contrib/unbound.plist42
-rw-r--r--contrib/unbound/contrib/unbound.spec112
-rw-r--r--contrib/unbound/contrib/unbound.spec_fedora433
-rw-r--r--contrib/unbound/contrib/unbound_cache.cmd105
-rwxr-xr-xcontrib/unbound/contrib/unbound_cache.sh174
-rw-r--r--contrib/unbound/contrib/unbound_cacti.tar.gzbin0 -> 73219 bytes
-rwxr-xr-xcontrib/unbound/contrib/unbound_munin_574
-rw-r--r--contrib/unbound/contrib/unbound_smf22.tar.gzbin0 -> 4578 bytes
-rwxr-xr-xcontrib/unbound/contrib/update-anchor.sh158
-rwxr-xr-xcontrib/unbound/contrib/validation-reporter.sh117
-rw-r--r--contrib/unbound/contrib/warmup.cmd153
-rwxr-xr-xcontrib/unbound/contrib/warmup.sh150
-rw-r--r--contrib/unbound/daemon/acl_list.c250
-rw-r--r--contrib/unbound/daemon/acl_list.h29
-rw-r--r--contrib/unbound/daemon/daemon.c33
-rw-r--r--contrib/unbound/daemon/daemon.h3
-rw-r--r--contrib/unbound/daemon/remote.c108
-rw-r--r--contrib/unbound/daemon/remote.h4
-rw-r--r--contrib/unbound/daemon/unbound.c84
-rw-r--r--contrib/unbound/daemon/worker.c68
-rw-r--r--contrib/unbound/dns64/dns64.c7
-rw-r--r--contrib/unbound/dnstap/dnstap.c2
-rw-r--r--contrib/unbound/doc/Changelog364
-rw-r--r--contrib/unbound/doc/README2
-rw-r--r--contrib/unbound/doc/example.conf53
-rw-r--r--contrib/unbound/doc/example.conf.in53
-rw-r--r--contrib/unbound/doc/libunbound.34
-rw-r--r--contrib/unbound/doc/libunbound.3.in4
-rw-r--r--contrib/unbound/doc/unbound-anchor.88
-rw-r--r--contrib/unbound/doc/unbound-anchor.8.in8
-rw-r--r--contrib/unbound/doc/unbound-checkconf.82
-rw-r--r--contrib/unbound/doc/unbound-checkconf.8.in2
-rw-r--r--contrib/unbound/doc/unbound-control.82
-rw-r--r--contrib/unbound/doc/unbound-control.8.in2
-rw-r--r--contrib/unbound/doc/unbound-host.12
-rw-r--r--contrib/unbound/doc/unbound-host.1.in2
-rw-r--r--contrib/unbound/doc/unbound.84
-rw-r--r--contrib/unbound/doc/unbound.8.in4
-rw-r--r--contrib/unbound/doc/unbound.conf.593
-rw-r--r--contrib/unbound/doc/unbound.conf.5.in93
-rw-r--r--contrib/unbound/doc/unbound.doxygen4
-rw-r--r--contrib/unbound/iterator/iter_fwd.c1
-rw-r--r--contrib/unbound/iterator/iter_hints.c1
-rw-r--r--contrib/unbound/iterator/iter_utils.c54
-rw-r--r--contrib/unbound/iterator/iter_utils.h12
-rw-r--r--contrib/unbound/iterator/iterator.c157
-rw-r--r--contrib/unbound/iterator/iterator.h30
-rw-r--r--contrib/unbound/libunbound/context.h4
-rw-r--r--contrib/unbound/libunbound/libunbound.c34
-rw-r--r--contrib/unbound/libunbound/libworker.c29
-rw-r--r--contrib/unbound/libunbound/libworker.h4
-rw-r--r--contrib/unbound/libunbound/python/libunbound.i2
-rw-r--r--contrib/unbound/libunbound/ubsyms.def1
-rw-r--r--contrib/unbound/libunbound/unbound-event.h152
-rw-r--r--contrib/unbound/libunbound/worker.h15
-rw-r--r--contrib/unbound/services/cache/dns.c7
-rw-r--r--contrib/unbound/services/listen_dnsport.c103
-rw-r--r--contrib/unbound/services/listen_dnsport.h6
-rw-r--r--contrib/unbound/services/localzone.c437
-rw-r--r--contrib/unbound/services/localzone.h58
-rw-r--r--contrib/unbound/services/mesh.c33
-rw-r--r--contrib/unbound/services/modstack.c9
-rw-r--r--contrib/unbound/services/outside_network.c159
-rw-r--r--contrib/unbound/services/outside_network.h15
-rw-r--r--contrib/unbound/sldns/keyraw.c40
-rw-r--r--contrib/unbound/sldns/parseutil.c4
-rw-r--r--contrib/unbound/sldns/rrdef.h5
-rw-r--r--contrib/unbound/sldns/str2wire.c4
-rw-r--r--contrib/unbound/sldns/wire2str.c4
-rw-r--r--contrib/unbound/sldns/wire2str.h18
-rw-r--r--contrib/unbound/smallapp/unbound-anchor.c27
-rw-r--r--contrib/unbound/smallapp/unbound-checkconf.c34
-rw-r--r--contrib/unbound/smallapp/unbound-control.c18
-rw-r--r--contrib/unbound/smallapp/unbound-host.c4
-rw-r--r--contrib/unbound/smallapp/worker_cb.c12
-rw-r--r--contrib/unbound/util/alloc.c4
-rw-r--r--contrib/unbound/util/config_file.c276
-rw-r--r--contrib/unbound/util/config_file.h135
-rw-r--r--contrib/unbound/util/configlexer.lex12
-rw-r--r--contrib/unbound/util/configparser.y161
-rw-r--r--contrib/unbound/util/data/dname.c18
-rw-r--r--contrib/unbound/util/data/msgencode.c22
-rw-r--r--contrib/unbound/util/data/msgparse.c60
-rw-r--r--contrib/unbound/util/data/msgparse.h28
-rw-r--r--contrib/unbound/util/data/msgreply.c154
-rw-r--r--contrib/unbound/util/data/msgreply.h52
-rw-r--r--contrib/unbound/util/fptr_wlist.c25
-rw-r--r--contrib/unbound/util/fptr_wlist.h2
-rw-r--r--contrib/unbound/util/iana_ports.inc10
-rw-r--r--contrib/unbound/util/module.h8
-rw-r--r--contrib/unbound/util/net_help.c6
-rw-r--r--contrib/unbound/util/netevent.c489
-rw-r--r--contrib/unbound/util/netevent.h31
-rw-r--r--contrib/unbound/util/storage/dnstree.c13
-rw-r--r--contrib/unbound/util/storage/dnstree.h11
-rw-r--r--contrib/unbound/util/storage/lookup3.c10
-rw-r--r--contrib/unbound/util/tube.c12
-rw-r--r--contrib/unbound/util/tube.h3
-rw-r--r--contrib/unbound/util/ub_event.c444
-rw-r--r--contrib/unbound/util/ub_event.h127
-rw-r--r--contrib/unbound/util/ub_event_pluggable.c692
-rw-r--r--contrib/unbound/util/winsock_event.c5
-rw-r--r--contrib/unbound/validator/autotrust.c5
-rw-r--r--contrib/unbound/validator/val_anchor.c2
-rw-r--r--contrib/unbound/validator/val_secalgo.c208
-rw-r--r--contrib/unbound/validator/val_secalgo.h8
-rw-r--r--contrib/unbound/validator/val_sigcrypt.c16
-rw-r--r--contrib/unbound/validator/validator.c6
-rw-r--r--crypto/openssh/kex.c1
-rw-r--r--etc/mtree/BSD.include.dist2
-rw-r--r--etc/rc.d/Makefile7
-rw-r--r--include/Makefile27
-rw-r--r--include/search.h23
-rw-r--r--lib/libc/db/btree/bt_close.c3
-rw-r--r--lib/libc/stdlib/tdelete.c24
-rw-r--r--lib/libc/stdlib/tfind.c7
-rw-r--r--lib/libc/stdlib/tsearch.329
-rw-r--r--lib/libc/stdlib/tsearch.c37
-rw-r--r--lib/libc/stdlib/twalk.c9
-rw-r--r--lib/libc/sys/getrlimit.212
-rw-r--r--lib/libc/sys/sigaction.276
-rw-r--r--lib/libc/tests/iconv/Makefile2
-rw-r--r--lib/libc/tests/stdio/printbasic_test.c4
-rw-r--r--lib/libc/tests/stdio/printfloat_test.c4
-rw-r--r--lib/libc/tests/stdlib/tsearch_test.c4
-rw-r--r--lib/libc/tests/sys/Makefile2
-rw-r--r--lib/libdevdctl/consumer.cc4
-rw-r--r--lib/libunbound/Makefile26
-rw-r--r--libexec/atf/atf-check/Makefile2
-rw-r--r--libexec/atf/atf-sh/Makefile2
-rw-r--r--libexec/ypxfr/ypxfr_getmap.c4
-rw-r--r--release/doc/en_US.ISO8859-1/errata/article.xml66
-rw-r--r--release/doc/share/xml/errata.xml7
-rw-r--r--release/doc/share/xml/security.xml7
-rw-r--r--sbin/init/init.c19
-rw-r--r--sbin/mount_msdosfs/mount_msdosfs.89
-rw-r--r--sbin/natd/natd.c2
-rw-r--r--share/misc/pci_vendors88
-rw-r--r--sys/amd64/amd64/initcpu.c14
-rw-r--r--sys/amd64/amd64/mp_machdep.c9
-rw-r--r--sys/amd64/amd64/sys_machdep.c5
-rw-r--r--sys/amd64/include/pcpu.h3
-rw-r--r--sys/arm/allwinner/axp209.c279
-rw-r--r--sys/arm/allwinner/axp209reg.h24
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_ft5406.c335
-rw-r--r--sys/arm/broadcom/bcm2835/files.bcm283x1
-rw-r--r--sys/arm/conf/BEAGLEBONE3
-rw-r--r--sys/arm/conf/RPI-B2
-rw-r--r--sys/arm/conf/RPI22
-rw-r--r--sys/arm/ti/ti_adc.c76
-rw-r--r--sys/arm/ti/ti_adcreg.h1
-rw-r--r--sys/arm/ti/ti_adcvar.h5
-rw-r--r--sys/boot/efi/Makefile4
-rw-r--r--sys/boot/fdt/dts/arm/rpi.dts5
-rw-r--r--sys/boot/fdt/dts/arm/rpi2.dts5
-rw-r--r--sys/boot/userboot/userboot/Makefile3
-rw-r--r--sys/cam/ata/ata_all.c11
-rw-r--r--sys/cam/ata/ata_da.c3
-rw-r--r--sys/cam/ctl/ctl.c25
-rw-r--r--sys/cam/ctl/ctl.h1
-rw-r--r--sys/cam/ctl/ctl_backend.c11
-rw-r--r--sys/cam/scsi/scsi_da.c3
-rw-r--r--sys/cam/scsi/scsi_enc_ses.c4
-rw-r--r--sys/cam/scsi/scsi_pass.c21
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c35
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c15
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c10
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c19
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c6
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c6
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h9
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c17
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c33
-rw-r--r--sys/cddl/dev/fbt/arm/fbt_isa.c3
-rw-r--r--sys/cddl/dev/fbt/fbt.c4
-rw-r--r--sys/cddl/dev/fbt/powerpc/fbt_isa.c3
-rw-r--r--sys/cddl/dev/fbt/x86/fbt_isa.c3
-rw-r--r--sys/conf/NOTES7
-rw-r--r--sys/conf/files5
-rw-r--r--sys/conf/options5
-rw-r--r--sys/dev/bxe/bxe.c190
-rw-r--r--sys/dev/bxe/bxe.h6
-rw-r--r--sys/dev/bxe/bxe_stats.h9
-rw-r--r--sys/dev/drm2/i915/i915_gem.c4
-rw-r--r--sys/dev/drm2/ttm/ttm_bo_vm.c2
-rw-r--r--sys/dev/e1000/if_lem.c19
-rw-r--r--sys/dev/evdev/cdev.c860
-rw-r--r--sys/dev/evdev/evdev.c949
-rw-r--r--sys/dev/evdev/evdev.h132
-rw-r--r--sys/dev/evdev/evdev_mt.c292
-rw-r--r--sys/dev/evdev/evdev_private.h200
-rw-r--r--sys/dev/evdev/evdev_utils.c334
-rw-r--r--sys/dev/evdev/input-event-codes.h819
-rw-r--r--sys/dev/evdev/input.h273
-rw-r--r--sys/dev/evdev/uinput.c712
-rw-r--r--sys/dev/evdev/uinput.h107
-rw-r--r--sys/dev/netmap/if_em_netmap.h2
-rw-r--r--sys/dev/pci/pci.c3
-rw-r--r--sys/dev/smbus/smbconf.h4
-rw-r--r--sys/dev/smbus/smbus.c198
-rw-r--r--sys/dev/sound/usb/uaudio.c35
-rw-r--r--sys/dev/usb/input/ukbd.c82
-rw-r--r--sys/dev/usb/input/ums.c261
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c20
-rw-r--r--sys/geom/mirror/g_mirror.c50
-rw-r--r--sys/geom/mirror/g_mirror.h1
-rw-r--r--sys/geom/mirror/g_mirror_ctl.c3
-rw-r--r--sys/i386/include/pcpu.h3
-rw-r--r--sys/kern/imgact_elf.c1
-rw-r--r--sys/kern/makesyscalls.sh3
-rw-r--r--sys/kern/subr_uio.c2
-rw-r--r--sys/kern/vfs_bio.c4
-rw-r--r--sys/modules/Makefile2
-rw-r--r--sys/modules/evdev/Makefile9
-rw-r--r--sys/modules/rpi_ft5406/Makefile10
-rw-r--r--sys/modules/uinput/Makefile9
-rw-r--r--sys/modules/usb/ukbd/Makefile2
-rw-r--r--sys/modules/usb/ums/Makefile4
-rw-r--r--sys/netinet/tcp_input.c28
-rw-r--r--sys/netinet/tcp_timewait.c4
-rw-r--r--sys/netinet/tcp_usrreq.c23
-rw-r--r--sys/netinet/udp_usrreq.c8
-rw-r--r--sys/netinet6/nd6.c4
-rw-r--r--sys/netinet6/nd6_rtr.c66
-rw-r--r--sys/netpfil/ipfw/ip_fw_table.c6
-rw-r--r--sys/sys/param.h12
-rw-r--r--sys/sys/procfs.h9
-rw-r--r--sys/ufs/ffs/ffs_vnops.c172
-rw-r--r--sys/vm/vm_fault.c12
-rw-r--r--sys/vm/vm_object.c10
-rw-r--r--sys/vm/vm_page.c29
-rw-r--r--sys/vm/vm_page.h4
-rw-r--r--sys/vm/vm_pageout.c51
-rw-r--r--sys/x86/include/x86_smp.h2
-rw-r--r--sys/x86/x86/mp_x86.c63
-rw-r--r--tests/sys/Makefile2
-rw-r--r--tests/sys/mac/bsdextended/matches_test.sh6
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc18
-rw-r--r--usr.bin/bsdcat/Makefile2
-rw-r--r--usr.bin/calendar/calendar.13
-rw-r--r--usr.bin/calendar/io.c2
-rw-r--r--usr.bin/cpio/Makefile2
-rw-r--r--usr.bin/elfdump/elfdump.c6
-rw-r--r--usr.bin/gcore/elfcore.c1
-rw-r--r--usr.bin/gzip/gzip.c2
-rw-r--r--usr.bin/indent/indent.c2
-rw-r--r--usr.bin/locale/locale.c4
-rw-r--r--usr.bin/localedef/collate.c12
-rw-r--r--usr.bin/mkcsmapper/mkcsmapper.115
-rw-r--r--usr.bin/mkcsmapper/yacc.y13
-rw-r--r--usr.bin/netstat/pfkey.c3
-rw-r--r--usr.bin/printenv/printenv.c4
-rw-r--r--usr.bin/procstat/procstat_files.c3
-rw-r--r--usr.bin/rpcgen/rpc_main.c4
-rw-r--r--usr.bin/sdiff/Makefile2
-rw-r--r--usr.bin/sdiff/common.c24
-rw-r--r--usr.bin/sdiff/common.h9
-rw-r--r--usr.bin/sdiff/edit.c12
-rw-r--r--usr.bin/sdiff/sdiff.c107
-rw-r--r--usr.bin/sed/tests/multi_test.sh1
-rw-r--r--usr.bin/systat/main.c6
-rw-r--r--usr.bin/tar/Makefile2
-rw-r--r--usr.bin/tee/tee.c35
-rw-r--r--usr.bin/top/machine.c63
-rw-r--r--usr.sbin/Makefile2
-rw-r--r--usr.sbin/bhyve/dbgport.c6
-rw-r--r--usr.sbin/bhyve/vga.c8
-rw-r--r--usr.sbin/ctladm/ctladm.817
-rw-r--r--usr.sbin/ctld/chap.c4
-rw-r--r--usr.sbin/ctld/keys.c2
-rw-r--r--usr.sbin/ctld/pdu.c4
-rwxr-xr-xusr.sbin/etcupdate/etcupdate.sh18
-rw-r--r--usr.sbin/fifolog/lib/fifolog_int.c2
-rw-r--r--usr.sbin/fifolog/lib/fifolog_reader.c2
-rw-r--r--usr.sbin/iscsid/chap.c4
-rw-r--r--usr.sbin/iscsid/keys.c2
-rw-r--r--usr.sbin/iscsid/pdu.c4
-rw-r--r--usr.sbin/pciconf/pciconf.c3
-rw-r--r--usr.sbin/pmcstat/pmcstat_log.h1
-rw-r--r--usr.sbin/rtsold/rtsol.c2
-rw-r--r--usr.sbin/syslogd/syslogd.c5
-rw-r--r--usr.sbin/unbound/checkconf/Makefile4
-rw-r--r--usr.sbin/unbound/control/Makefile4
-rw-r--r--usr.sbin/unbound/daemon/Makefile5
399 files changed, 19838 insertions, 2864 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1
index 4a18cb5..c148967 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -1570,7 +1570,7 @@ _strfile= usr.bin/fortune/strfile
_gperf= gnu/usr.bin/gperf
.endif
-.if ${MK_GROFF} != "no"
+.if ${MK_SHAREDOCS} != "no" && ${MK_GROFF} != "no"
_groff= gnu/usr.bin/groff \
usr.bin/soelim
.endif
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c
index 72fd08a..2d8c24a 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c
@@ -581,6 +581,7 @@ int
dt_printf(dtrace_hdl_t *dtp, FILE *fp, const char *format, ...)
{
va_list ap;
+ va_list ap2;
int n;
#ifndef illumos
@@ -605,11 +606,13 @@ dt_printf(dtrace_hdl_t *dtp, FILE *fp, const char *format, ...)
len = dtp->dt_sprintf_buflen - len;
assert(len >= 0);
- if ((n = vsnprintf(buf, len, format, ap)) < 0)
+ va_copy(ap2, ap);
+ if ((n = vsnprintf(buf, len, format, ap2)) < 0)
n = dt_set_errno(dtp, errno);
+ va_end(ap2);
va_end(ap);
-
+
return (n);
}
@@ -640,11 +643,14 @@ dt_printf(dtrace_hdl_t *dtp, FILE *fp, const char *format, ...)
dtp->dt_buffered_buf[0] = '\0';
}
- if ((needed = vsnprintf(NULL, 0, format, ap)) < 0) {
+ va_copy(ap2, ap);
+ if ((needed = vsnprintf(NULL, 0, format, ap2)) < 0) {
rval = dt_set_errno(dtp, errno);
+ va_end(ap2);
va_end(ap);
return (rval);
}
+ va_end(ap2);
if (needed == 0) {
va_end(ap);
@@ -670,12 +676,15 @@ dt_printf(dtrace_hdl_t *dtp, FILE *fp, const char *format, ...)
dtp->dt_buffered_size <<= 1;
}
+ va_copy(ap2, ap);
if (vsnprintf(&dtp->dt_buffered_buf[dtp->dt_buffered_offs],
- avail, format, ap) < 0) {
+ avail, format, ap2) < 0) {
rval = dt_set_errno(dtp, errno);
+ va_end(ap2);
va_end(ap);
return (rval);
}
+ va_end(ap2);
dtp->dt_buffered_offs += needed;
assert(dtp->dt_buffered_buf[dtp->dt_buffered_offs] == '\0');
@@ -683,8 +692,10 @@ dt_printf(dtrace_hdl_t *dtp, FILE *fp, const char *format, ...)
return (0);
}
- n = vfprintf(fp, format, ap);
+ va_copy(ap2, ap);
+ n = vfprintf(fp, format, ap2);
fflush(fp);
+ va_end(ap2);
va_end(ap);
if (n < 0) {
diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS
index f672d3d..dd4cfd5 100644
--- a/contrib/libarchive/NEWS
+++ b/contrib/libarchive/NEWS
@@ -1,3 +1,6 @@
+Oct 23, 2016: libarchive 3.2.2 released
+ Security release
+
Jun 20, 2016: libarchive 3.2.1 released
This fixes a handful of security and other critical issues with 3.2.0
diff --git a/contrib/libarchive/cat/test/main.c b/contrib/libarchive/cat/test/main.c
index 29f7b14..a579842 100644
--- a/contrib/libarchive/cat/test/main.c
+++ b/contrib/libarchive/cat/test/main.c
@@ -129,6 +129,13 @@
# include <crtdbg.h>
#endif
+mode_t umasked(mode_t expected_mode)
+{
+ mode_t mode = umask(0);
+ umask(mode);
+ return expected_mode & ~mode;
+}
+
/* Path to working directory for current test */
const char *testworkdir;
#ifdef PROGRAM
@@ -1156,6 +1163,35 @@ assertion_file_contains_lines_any_order(const char *file, int line,
return (0);
}
+/* Verify that a text file does not contains the specified strings */
+int
+assertion_file_contains_no_invalid_strings(const char *file, int line,
+ const char *pathname, const char *strings[])
+{
+ char *buff;
+ int i;
+
+ buff = slurpfile(NULL, "%s", pathname);
+ if (buff == NULL) {
+ failure_start(file, line, "Can't read file: %s", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+
+ for (i = 0; strings[i] != NULL; ++i) {
+ if (strstr(buff, strings[i]) != NULL) {
+ failure_start(file, line, "Invalid string in %s: %s", pathname,
+ strings[i]);
+ failure_finish(NULL);
+ free(buff);
+ return(0);
+ }
+ }
+
+ free(buff);
+ return (0);
+}
+
/* Test that two paths point to the same file. */
/* As a side-effect, asserts that both files exist. */
static int
@@ -1293,6 +1329,11 @@ assertion_file_time(const char *file, int line,
switch (type) {
case 'a': filet_nsec = st.st_atimespec.tv_nsec; break;
case 'b': filet = st.st_birthtime;
+ /* FreeBSD filesystems that don't support birthtime
+ * (e.g., UFS1) always return -1 here. */
+ if (filet == -1) {
+ return (1);
+ }
filet_nsec = st.st_birthtimespec.tv_nsec; break;
case 'm': filet_nsec = st.st_mtimespec.tv_nsec; break;
default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
@@ -1370,6 +1411,8 @@ assertion_file_mode(const char *file, int line, const char *pathname, int expect
assertion_count(file, line);
#if defined(_WIN32) && !defined(__CYGWIN__)
failure_start(file, line, "assertFileMode not yet implemented for Windows");
+ (void)mode; /* UNUSED */
+ (void)r; /* UNUSED */
#else
{
struct stat st;
@@ -1424,7 +1467,7 @@ assertion_file_nlinks(const char *file, int line,
assertion_count(file, line);
r = lstat(pathname, &st);
if (r == 0 && (int)st.st_nlink == nlinks)
- return (1);
+ return (1);
failure_start(file, line, "File %s has %d links, expected %d",
pathname, st.st_nlink, nlinks);
failure_finish(NULL);
@@ -1660,6 +1703,7 @@ assertion_make_file(const char *file, int line,
if (0 != chmod(path, mode)) {
failure_start(file, line, "Could not chmod %s", path);
failure_finish(NULL);
+ close(fd);
return (0);
}
if (contents != NULL) {
@@ -1674,6 +1718,7 @@ assertion_make_file(const char *file, int line,
failure_start(file, line,
"Could not write to %s", path);
failure_finish(NULL);
+ close(fd);
return (0);
}
}
diff --git a/contrib/libarchive/cat/test/test.h b/contrib/libarchive/cat/test/test.h
index 1d21964..c002a2c 100644
--- a/contrib/libarchive/cat/test/test.h
+++ b/contrib/libarchive/cat/test/test.h
@@ -174,6 +174,9 @@
/* Assert that file contents match a string. */
#define assertFileContents(data, data_size, pathname) \
assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
+/* Verify that a file does not contain invalid strings */
+#define assertFileContainsNoInvalidStrings(pathname, strings) \
+ assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings)
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
@@ -182,6 +185,8 @@
assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
#define assertFileSize(pathname, size) \
assertion_file_size(__FILE__, __LINE__, pathname, size)
+#define assertFileMode(pathname, mode) \
+ assertion_file_mode(__FILE__, __LINE__, pathname, mode)
#define assertTextFileContents(text, pathname) \
assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
#define assertFileContainsLinesAnyOrder(pathname, lines) \
@@ -239,6 +244,7 @@ int assertion_file_atime_recent(const char *, int, const char *);
int assertion_file_birthtime(const char *, int, const char *, long, long);
int assertion_file_birthtime_recent(const char *, int, const char *);
int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
+int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **);
int assertion_file_contents(const char *, int, const void *, int, const char *);
int assertion_file_exists(const char *, int, const char *);
int assertion_file_mode(const char *, int, const char *, int);
@@ -327,6 +333,9 @@ void copy_reference_file(const char *);
*/
void extract_reference_files(const char **);
+/* Subtract umask from mode */
+mode_t umasked(mode_t expected_mode);
+
/* Path to working directory for current test */
extern const char *testworkdir;
diff --git a/contrib/libarchive/cpio/test/main.c b/contrib/libarchive/cpio/test/main.c
index 541a550..d6842f5 100644
--- a/contrib/libarchive/cpio/test/main.c
+++ b/contrib/libarchive/cpio/test/main.c
@@ -130,6 +130,13 @@ __FBSDID("$FreeBSD$");
# include <crtdbg.h>
#endif
+mode_t umasked(mode_t expected_mode)
+{
+ mode_t mode = umask(0);
+ umask(mode);
+ return expected_mode & ~mode;
+}
+
/* Path to working directory for current test */
const char *testworkdir;
#ifdef PROGRAM
@@ -1157,6 +1164,35 @@ assertion_file_contains_lines_any_order(const char *file, int line,
return (0);
}
+/* Verify that a text file does not contains the specified strings */
+int
+assertion_file_contains_no_invalid_strings(const char *file, int line,
+ const char *pathname, const char *strings[])
+{
+ char *buff;
+ int i;
+
+ buff = slurpfile(NULL, "%s", pathname);
+ if (buff == NULL) {
+ failure_start(file, line, "Can't read file: %s", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+
+ for (i = 0; strings[i] != NULL; ++i) {
+ if (strstr(buff, strings[i]) != NULL) {
+ failure_start(file, line, "Invalid string in %s: %s", pathname,
+ strings[i]);
+ failure_finish(NULL);
+ free(buff);
+ return(0);
+ }
+ }
+
+ free(buff);
+ return (0);
+}
+
/* Test that two paths point to the same file. */
/* As a side-effect, asserts that both files exist. */
static int
@@ -1294,6 +1330,11 @@ assertion_file_time(const char *file, int line,
switch (type) {
case 'a': filet_nsec = st.st_atimespec.tv_nsec; break;
case 'b': filet = st.st_birthtime;
+ /* FreeBSD filesystems that don't support birthtime
+ * (e.g., UFS1) always return -1 here. */
+ if (filet == -1) {
+ return (1);
+ }
filet_nsec = st.st_birthtimespec.tv_nsec; break;
case 'm': filet_nsec = st.st_mtimespec.tv_nsec; break;
default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
@@ -1371,6 +1412,8 @@ assertion_file_mode(const char *file, int line, const char *pathname, int expect
assertion_count(file, line);
#if defined(_WIN32) && !defined(__CYGWIN__)
failure_start(file, line, "assertFileMode not yet implemented for Windows");
+ (void)mode; /* UNUSED */
+ (void)r; /* UNUSED */
#else
{
struct stat st;
@@ -1425,7 +1468,7 @@ assertion_file_nlinks(const char *file, int line,
assertion_count(file, line);
r = lstat(pathname, &st);
if (r == 0 && (int)st.st_nlink == nlinks)
- return (1);
+ return (1);
failure_start(file, line, "File %s has %d links, expected %d",
pathname, st.st_nlink, nlinks);
failure_finish(NULL);
@@ -1661,6 +1704,7 @@ assertion_make_file(const char *file, int line,
if (0 != chmod(path, mode)) {
failure_start(file, line, "Could not chmod %s", path);
failure_finish(NULL);
+ close(fd);
return (0);
}
if (contents != NULL) {
@@ -1675,6 +1719,7 @@ assertion_make_file(const char *file, int line,
failure_start(file, line,
"Could not write to %s", path);
failure_finish(NULL);
+ close(fd);
return (0);
}
}
diff --git a/contrib/libarchive/cpio/test/test.h b/contrib/libarchive/cpio/test/test.h
index 1d21964..c002a2c 100644
--- a/contrib/libarchive/cpio/test/test.h
+++ b/contrib/libarchive/cpio/test/test.h
@@ -174,6 +174,9 @@
/* Assert that file contents match a string. */
#define assertFileContents(data, data_size, pathname) \
assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
+/* Verify that a file does not contain invalid strings */
+#define assertFileContainsNoInvalidStrings(pathname, strings) \
+ assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings)
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
@@ -182,6 +185,8 @@
assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
#define assertFileSize(pathname, size) \
assertion_file_size(__FILE__, __LINE__, pathname, size)
+#define assertFileMode(pathname, mode) \
+ assertion_file_mode(__FILE__, __LINE__, pathname, mode)
#define assertTextFileContents(text, pathname) \
assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
#define assertFileContainsLinesAnyOrder(pathname, lines) \
@@ -239,6 +244,7 @@ int assertion_file_atime_recent(const char *, int, const char *);
int assertion_file_birthtime(const char *, int, const char *, long, long);
int assertion_file_birthtime_recent(const char *, int, const char *);
int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
+int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **);
int assertion_file_contents(const char *, int, const void *, int, const char *);
int assertion_file_exists(const char *, int, const char *);
int assertion_file_mode(const char *, int, const char *, int);
@@ -327,6 +333,9 @@ void copy_reference_file(const char *);
*/
void extract_reference_files(const char **);
+/* Subtract umask from mode */
+mode_t umasked(mode_t expected_mode);
+
/* Path to working directory for current test */
extern const char *testworkdir;
diff --git a/contrib/libarchive/libarchive/archive.h b/contrib/libarchive/libarchive/archive.h
index 013eee8..18462bb 100644
--- a/contrib/libarchive/libarchive/archive.h
+++ b/contrib/libarchive/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3002001
+#define ARCHIVE_VERSION_NUMBER 3002002
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.2.1"
+#define ARCHIVE_VERSION_ONLY_STRING "3.2.2"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
diff --git a/contrib/libarchive/libarchive/archive_entry.h b/contrib/libarchive/libarchive/archive_entry.h
index 3a90ac7..1150889 100644
--- a/contrib/libarchive/libarchive/archive_entry.h
+++ b/contrib/libarchive/libarchive/archive_entry.h
@@ -29,7 +29,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3002001
+#define ARCHIVE_VERSION_NUMBER 3002002
/*
* Note: archive_entry.h is for use outside of libarchive; the
diff --git a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c b/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
index 4cffdeb..f4a861c 100644
--- a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
+++ b/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
@@ -627,7 +627,6 @@ translate_acl(struct archive_read_disk *a,
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unknown ACL brand");
return (ARCHIVE_WARN);
- break;
}
#endif
diff --git a/contrib/libarchive/libarchive/archive_read_disk_set_standard_lookup.c b/contrib/libarchive/libarchive/archive_read_disk_set_standard_lookup.c
index 60a9376..7191969 100644
--- a/contrib/libarchive/libarchive/archive_read_disk_set_standard_lookup.c
+++ b/contrib/libarchive/libarchive/archive_read_disk_set_standard_lookup.c
@@ -232,6 +232,7 @@ static const char *
lookup_uname_helper(struct name_cache *cache, id_t id)
{
struct passwd *result;
+ (void)cache; /* UNUSED */
result = getpwuid((uid_t)id);
@@ -298,6 +299,7 @@ static const char *
lookup_gname_helper(struct name_cache *cache, id_t id)
{
struct group *result;
+ (void)cache; /* UNUSED */
result = getgrgid((gid_t)id);
diff --git a/contrib/libarchive/libarchive/test/main.c b/contrib/libarchive/libarchive/test/main.c
index 0f9c64b..304c7f6 100644
--- a/contrib/libarchive/libarchive/test/main.c
+++ b/contrib/libarchive/libarchive/test/main.c
@@ -128,6 +128,13 @@ __FBSDID("$FreeBSD$");
# include <crtdbg.h>
#endif
+mode_t umasked(mode_t expected_mode)
+{
+ mode_t mode = umask(0);
+ umask(mode);
+ return expected_mode & ~mode;
+}
+
/* Path to working directory for current test */
const char *testworkdir;
#ifdef PROGRAM
@@ -1155,6 +1162,35 @@ assertion_file_contains_lines_any_order(const char *file, int line,
return (0);
}
+/* Verify that a text file does not contains the specified strings */
+int
+assertion_file_contains_no_invalid_strings(const char *file, int line,
+ const char *pathname, const char *strings[])
+{
+ char *buff;
+ int i;
+
+ buff = slurpfile(NULL, "%s", pathname);
+ if (buff == NULL) {
+ failure_start(file, line, "Can't read file: %s", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+
+ for (i = 0; strings[i] != NULL; ++i) {
+ if (strstr(buff, strings[i]) != NULL) {
+ failure_start(file, line, "Invalid string in %s: %s", pathname,
+ strings[i]);
+ failure_finish(NULL);
+ free(buff);
+ return(0);
+ }
+ }
+
+ free(buff);
+ return (0);
+}
+
/* Test that two paths point to the same file. */
/* As a side-effect, asserts that both files exist. */
static int
@@ -1364,6 +1400,33 @@ assertion_file_birthtime_recent(const char *file, int line,
return assertion_file_time(file, line, pathname, 0, 0, 'b', 1);
}
+/* Verify mode of 'pathname'. */
+int
+assertion_file_mode(const char *file, int line, const char *pathname, int expected_mode)
+{
+ int mode;
+ int r;
+
+ assertion_count(file, line);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ failure_start(file, line, "assertFileMode not yet implemented for Windows");
+ (void)mode; /* UNUSED */
+ (void)r; /* UNUSED */
+#else
+ {
+ struct stat st;
+ r = lstat(pathname, &st);
+ mode = (int)(st.st_mode & 0777);
+ }
+ if (r == 0 && mode == expected_mode)
+ return (1);
+ failure_start(file, line, "File %s has mode %o, expected %o",
+ pathname, mode, expected_mode);
+#endif
+ failure_finish(NULL);
+ return (0);
+}
+
/* Verify mtime of 'pathname'. */
int
assertion_file_mtime(const char *file, int line,
@@ -1403,7 +1466,7 @@ assertion_file_nlinks(const char *file, int line,
assertion_count(file, line);
r = lstat(pathname, &st);
if (r == 0 && (int)st.st_nlink == nlinks)
- return (1);
+ return (1);
failure_start(file, line, "File %s has %d links, expected %d",
pathname, st.st_nlink, nlinks);
failure_finish(NULL);
@@ -1440,31 +1503,6 @@ assertion_file_size(const char *file, int line, const char *pathname, long size)
return (0);
}
-/* Verify mode of 'pathname'. */
-int
-assertion_file_mode(const char *file, int line, const char *pathname, int expected_mode)
-{
- int mode;
- int r;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- failure_start(file, line, "assertFileMode not yet implemented for Windows");
-#else
- {
- struct stat st;
- r = lstat(pathname, &st);
- mode = (int)(st.st_mode & 0777);
- }
- if (r == 0 && mode == expected_mode)
- return (1);
- failure_start(file, line, "File %s has mode %o, expected %o",
- pathname, mode, expected_mode);
-#endif
- failure_finish(NULL);
- return (0);
-}
-
/* Assert that 'pathname' is a dir. If mode >= 0, verify that too. */
int
assertion_is_dir(const char *file, int line, const char *pathname, int mode)
@@ -1664,6 +1702,7 @@ assertion_make_file(const char *file, int line,
if (0 != chmod(path, mode)) {
failure_start(file, line, "Could not chmod %s", path);
failure_finish(NULL);
+ close(fd);
return (0);
}
if (contents != NULL) {
@@ -1678,6 +1717,7 @@ assertion_make_file(const char *file, int line,
failure_start(file, line,
"Could not write to %s", path);
failure_finish(NULL);
+ close(fd);
return (0);
}
}
diff --git a/contrib/libarchive/libarchive/test/test.h b/contrib/libarchive/libarchive/test/test.h
index bcf6869..f7ec59f 100644
--- a/contrib/libarchive/libarchive/test/test.h
+++ b/contrib/libarchive/libarchive/test/test.h
@@ -174,6 +174,9 @@
/* Assert that file contents match a string. */
#define assertFileContents(data, data_size, pathname) \
assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
+/* Verify that a file does not contain invalid strings */
+#define assertFileContainsNoInvalidStrings(pathname, strings) \
+ assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings)
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
@@ -241,14 +244,15 @@ int assertion_file_atime_recent(const char *, int, const char *);
int assertion_file_birthtime(const char *, int, const char *, long, long);
int assertion_file_birthtime_recent(const char *, int, const char *);
int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
+int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **);
int assertion_file_contents(const char *, int, const void *, int, const char *);
int assertion_file_exists(const char *, int, const char *);
+int assertion_file_mode(const char *, int, const char *, int);
int assertion_file_mtime(const char *, int, const char *, long, long);
int assertion_file_mtime_recent(const char *, int, const char *);
int assertion_file_nlinks(const char *, int, const char *, int);
int assertion_file_not_exists(const char *, int, const char *);
int assertion_file_size(const char *, int, const char *, long);
-int assertion_file_mode(const char *, int, const char *, int);
int assertion_is_dir(const char *, int, const char *, int);
int assertion_is_hardlink(const char *, int, const char *, const char *);
int assertion_is_not_hardlink(const char *, int, const char *, const char *);
@@ -329,6 +333,9 @@ void copy_reference_file(const char *);
*/
void extract_reference_files(const char **);
+/* Subtract umask from mode */
+mode_t umasked(mode_t expected_mode);
+
/* Path to working directory for current test */
extern const char *testworkdir;
diff --git a/contrib/libarchive/libarchive/test/test_read_format_mtree_crash747.c b/contrib/libarchive/libarchive/test/test_read_format_mtree_crash747.c
index c082845..9500bba 100644
--- a/contrib/libarchive/libarchive/test/test_read_format_mtree_crash747.c
+++ b/contrib/libarchive/libarchive/test/test_read_format_mtree_crash747.c
@@ -33,6 +33,11 @@ DEFINE_TEST(test_read_format_mtree_crash747)
const char *reffile = "test_read_format_mtree_crash747.mtree.bz2";
struct archive *a;
+ if (archive_bzlib_version() == NULL) {
+ skipping("This test requires bzlib");
+ return;
+ }
+
extract_reference_file(reffile);
assert((a = archive_read_new()) != NULL);
diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c b/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c
index 6c8aa8e..42faed3 100644
--- a/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c
+++ b/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c
@@ -50,6 +50,11 @@ DEFINE_TEST(test_read_format_zip_high_compression)
size_t s;
int64_t o;
+ if (archive_zlib_version() == NULL) {
+ skipping("Zip compression test requires zlib");
+ return;
+ }
+
extract_reference_file(refname);
p = slurpfile(&archive_size, refname);
@@ -82,6 +87,11 @@ DEFINE_TEST(test_read_format_zip_high_compression2)
char *body, *body_read, *buff;
int n;
+ if (archive_zlib_version() == NULL) {
+ skipping("Zip compression test requires zlib");
+ return;
+ }
+
assert((body = malloc(body_size)) != NULL);
assert((body_read = malloc(body_size)) != NULL);
assert((buff = malloc(buff_size)) != NULL);
diff --git a/contrib/libarchive/libarchive/test/test_read_set_format.c b/contrib/libarchive/libarchive/test/test_read_set_format.c
index f9be978..fb5e004 100644
--- a/contrib/libarchive/libarchive/test/test_read_set_format.c
+++ b/contrib/libarchive/libarchive/test/test_read_set_format.c
@@ -133,11 +133,12 @@ DEFINE_TEST(test_read_append_filter)
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_GZIP);
- if (r == ARCHIVE_WARN && !canGzip()) {
- skipping("gzip reading not fully supported on this platform");
+ if (r != ARCHIVE_OK && archive_zlib_version() == NULL && !canGzip()) {
+ skipping("gzip tests require zlib or working gzip command");
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
return;
}
+ assertEqualIntA(a, ARCHIVE_OK, r);
assertEqualInt(ARCHIVE_OK,
archive_read_open_memory(a, archive, sizeof(archive)));
assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae));
@@ -200,6 +201,11 @@ DEFINE_TEST(test_read_append_filter_wrong_program)
{
struct archive_entry *ae;
struct archive *a;
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ FILE * fp;
+ int fd;
+ fpos_t pos;
+#endif
/*
* If we have "bunzip2 -q", try using that.
@@ -208,6 +214,15 @@ DEFINE_TEST(test_read_append_filter_wrong_program)
skipping("Can't run bunzip2 program on this platform");
return;
}
+
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ /* bunzip2 will write to stderr, redirect it to a file */
+ fflush(stderr);
+ fgetpos(stderr, &pos);
+ fd = dup(fileno(stderr));
+ fp = freopen("stderr1", "w", stderr);
+#endif
+
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
assertEqualIntA(a, ARCHIVE_OK,
@@ -217,4 +232,16 @@ DEFINE_TEST(test_read_append_filter_wrong_program)
assertA(archive_read_next_header(a, &ae) < (ARCHIVE_WARN));
assertEqualIntA(a, ARCHIVE_WARN, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ /* restore stderr and verify results */
+ if (fp != NULL) {
+ fflush(stderr);
+ dup2(fd, fileno(stderr));
+ close(fd);
+ clearerr(stderr);
+ fsetpos(stderr, &pos);
+ }
+ assertTextFileContents("bunzip2: (stdin) is not a bzip2 file.\n", "stderr1");
+#endif
}
diff --git a/contrib/libarchive/libarchive/test/test_write_format_iso9660.c b/contrib/libarchive/libarchive/test/test_write_format_iso9660.c
index 1ea69a1..ee6db6f 100644
--- a/contrib/libarchive/libarchive/test/test_write_format_iso9660.c
+++ b/contrib/libarchive/libarchive/test/test_write_format_iso9660.c
@@ -117,8 +117,8 @@ DEFINE_TEST(test_write_format_iso9660)
*/
dirname[0] = '\0';
strcpy(dir, "/dir0");
- for (i = 0; i < 10; i++) {
- dir[4] = '0' + i;
+ for (i = 0; i < 13; i++) {
+ dir[4] = "0123456789ABCDEF"[i];
if (i == 0)
strcat(dirname, dir+1);
else
@@ -134,6 +134,19 @@ DEFINE_TEST(test_write_format_iso9660)
archive_entry_free(ae);
}
+ strcat(dirname, "/file");
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_set_atime(ae, 2, 20);
+ archive_entry_set_birthtime(ae, 3, 30);
+ archive_entry_set_ctime(ae, 4, 40);
+ archive_entry_set_mtime(ae, 5, 50);
+ archive_entry_copy_pathname(ae, dirname);
+ archive_entry_set_mode(ae, S_IFREG | 0755);
+ archive_entry_set_size(ae, 8);
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+ archive_entry_free(ae);
+ assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));
+
/*
* "dir0/dir1/file1" has 8 bytes of data.
*/
@@ -333,6 +346,45 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualInt(2048, archive_entry_size(ae));
/*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(2, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_birthtime(ae));
+ assertEqualInt(4, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0555) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(2, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_birthtime(ae));
+ assertEqualInt(4, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0555) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(2, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_birthtime(ae));
+ assertEqualInt(4, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0555) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
* Read "hardlnk"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
@@ -386,6 +438,21 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualMem(buff2, "12345678", 8);
/*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(2, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_birthtime(ae));
+ assertEqualInt(4, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file", archive_entry_pathname(ae));
+ assert((AE_IFREG | 0555) == archive_entry_mode(ae));
+ assertEqualInt(1, archive_entry_nlink(ae));
+ assertEqualInt(8, archive_entry_size(ae));
+ assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
+ assertEqualMem(buff2, "12345678", 8);
+
+ /*
* Read "dir0/dir1/file1"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
@@ -580,29 +647,65 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualInt(2048, archive_entry_size(ae));
/*
- * Read "hardlnk"
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_atime(ae));
assertEqualInt(5, archive_entry_ctime(ae));
assertEqualInt(5, archive_entry_mtime(ae));
- assertEqualString("hardlnk", archive_entry_pathname(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "file"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("file", archive_entry_pathname(ae));
assert((AE_IFREG | 0400) == archive_entry_mode(ae));
- assertEqualInt(2, archive_entry_nlink(ae));
assertEqualInt(8, archive_entry_size(ae));
assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
assertEqualMem(buff2, "12345678", 8);
/*
- * Read "file"
+ * Read "hardlnk"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_atime(ae));
assertEqualInt(5, archive_entry_ctime(ae));
assertEqualInt(5, archive_entry_mtime(ae));
- assertEqualString("file", archive_entry_pathname(ae));
- assertEqualString("hardlnk", archive_entry_hardlink(ae));
+ assertEqualString("hardlnk", archive_entry_pathname(ae));
+ assertEqualString("file", archive_entry_hardlink(ae));
assert((AE_IFREG | 0400) == archive_entry_mode(ae));
+ assertEqualInt(2, archive_entry_nlink(ae));
assertEqualInt(0, archive_entry_size(ae));
assertEqualIntA(a, 0, archive_read_data(a, buff2, 10));
@@ -625,6 +728,22 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualMem(buff2, "12345678", 8);
/*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString(
+ "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file",
+ archive_entry_pathname(ae));
+ assert((AE_IFREG | 0400) == archive_entry_mode(ae));
+ assertEqualInt(1, archive_entry_nlink(ae));
+ assertEqualInt(8, archive_entry_size(ae));
+ assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
+ assertEqualMem(buff2, "12345678", 8);
+
+ /*
* Read "dir0/dir1/file1"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
@@ -746,6 +865,42 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualInt(2048, archive_entry_size(ae));
/*
+ * Read "rr_moved/dir7/dir8/dir9/dira"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("RR_MOVED/DIR7/DIR8/DIR9/DIRA",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "rr_moved/dir7/dir8/dir9/dira/dirB"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("RR_MOVED/DIR7/DIR8/DIR9/DIRA/DIRB",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "rr_moved/dir7/dir8/dir9/dirA/dirB/dirC"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("RR_MOVED/DIR7/DIR8/DIR9/DIRA/DIRB/DIRC",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
* Read "dir0"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
@@ -827,33 +982,35 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualInt(2048, archive_entry_size(ae));
/*
- * Read "file"
+ * Read "hardlink"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_atime(ae));
- assertEqualInt(0, archive_entry_birthtime(ae));
assertEqualInt(5, archive_entry_ctime(ae));
assertEqualInt(5, archive_entry_mtime(ae));
- assertEqualString("FILE", archive_entry_pathname(ae));
+ assertEqualString("HARDLNK", archive_entry_pathname(ae));
+ assertEqualString(NULL, archive_entry_hardlink(ae));
assert((AE_IFREG | 0400) == archive_entry_mode(ae));
- assertEqualInt(2, archive_entry_nlink(ae));
assertEqualInt(8, archive_entry_size(ae));
assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
assertEqualMem(buff2, "12345678", 8);
/*
- * Read "hardlink"
+ * Read "file"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(0, archive_entry_birthtime(ae));
assertEqualInt(5, archive_entry_ctime(ae));
assertEqualInt(5, archive_entry_mtime(ae));
- assertEqualString("HARDLNK", archive_entry_pathname(ae));
- assertEqualString("FILE", archive_entry_hardlink(ae));
+ assertEqualString("FILE", archive_entry_pathname(ae));
+ assertEqualString("HARDLNK", archive_entry_hardlink(ae));
assert((AE_IFREG | 0400) == archive_entry_mode(ae));
+ assertEqualInt(2, archive_entry_nlink(ae));
assertEqualInt(0, archive_entry_size(ae));
assertEqualIntA(a, 0, archive_read_data(a, buff2, 10));
+
/*
* Read longname
*/
@@ -871,6 +1028,22 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualMem(buff2, "12345678", 8);
/*
+ * Read "rr_moved/dir7/dir8/dir9/dirA/dirB/dirC/file"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString(
+ "RR_MOVED/DIR7/DIR8/DIR9/DIRA/DIRB/DIRC/FILE",
+ archive_entry_pathname(ae));
+ assert((AE_IFREG | 0400) == archive_entry_mode(ae));
+ assertEqualInt(1, archive_entry_nlink(ae));
+ assertEqualInt(8, archive_entry_size(ae));
+ assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
+ assertEqualMem(buff2, "12345678", 8);
+
+ /*
* Read "dir0/dir1/file1"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
diff --git a/contrib/libarchive/tar/test/main.c b/contrib/libarchive/tar/test/main.c
index 8bf1d36..6bffee2 100644
--- a/contrib/libarchive/tar/test/main.c
+++ b/contrib/libarchive/tar/test/main.c
@@ -1164,6 +1164,35 @@ assertion_file_contains_lines_any_order(const char *file, int line,
return (0);
}
+/* Verify that a text file does not contains the specified strings */
+int
+assertion_file_contains_no_invalid_strings(const char *file, int line,
+ const char *pathname, const char *strings[])
+{
+ char *buff;
+ int i;
+
+ buff = slurpfile(NULL, "%s", pathname);
+ if (buff == NULL) {
+ failure_start(file, line, "Can't read file: %s", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+
+ for (i = 0; strings[i] != NULL; ++i) {
+ if (strstr(buff, strings[i]) != NULL) {
+ failure_start(file, line, "Invalid string in %s: %s", pathname,
+ strings[i]);
+ failure_finish(NULL);
+ free(buff);
+ return(0);
+ }
+ }
+
+ free(buff);
+ return (0);
+}
+
/* Test that two paths point to the same file. */
/* As a side-effect, asserts that both files exist. */
static int
@@ -1301,6 +1330,11 @@ assertion_file_time(const char *file, int line,
switch (type) {
case 'a': filet_nsec = st.st_atimespec.tv_nsec; break;
case 'b': filet = st.st_birthtime;
+ /* FreeBSD filesystems that don't support birthtime
+ * (e.g., UFS1) always return -1 here. */
+ if (filet == -1) {
+ return (1);
+ }
filet_nsec = st.st_birthtimespec.tv_nsec; break;
case 'm': filet_nsec = st.st_mtimespec.tv_nsec; break;
default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
@@ -1378,6 +1412,8 @@ assertion_file_mode(const char *file, int line, const char *pathname, int expect
assertion_count(file, line);
#if defined(_WIN32) && !defined(__CYGWIN__)
failure_start(file, line, "assertFileMode not yet implemented for Windows");
+ (void)mode; /* UNUSED */
+ (void)r; /* UNUSED */
#else
{
struct stat st;
@@ -1432,7 +1468,7 @@ assertion_file_nlinks(const char *file, int line,
assertion_count(file, line);
r = lstat(pathname, &st);
if (r == 0 && (int)st.st_nlink == nlinks)
- return (1);
+ return (1);
failure_start(file, line, "File %s has %d links, expected %d",
pathname, st.st_nlink, nlinks);
failure_finish(NULL);
@@ -1668,6 +1704,7 @@ assertion_make_file(const char *file, int line,
if (0 != chmod(path, mode)) {
failure_start(file, line, "Could not chmod %s", path);
failure_finish(NULL);
+ close(fd);
return (0);
}
if (contents != NULL) {
@@ -1682,6 +1719,7 @@ assertion_make_file(const char *file, int line,
failure_start(file, line,
"Could not write to %s", path);
failure_finish(NULL);
+ close(fd);
return (0);
}
}
diff --git a/contrib/libarchive/tar/test/test.h b/contrib/libarchive/tar/test/test.h
index 340eadc..c002a2c 100644
--- a/contrib/libarchive/tar/test/test.h
+++ b/contrib/libarchive/tar/test/test.h
@@ -174,6 +174,9 @@
/* Assert that file contents match a string. */
#define assertFileContents(data, data_size, pathname) \
assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
+/* Verify that a file does not contain invalid strings */
+#define assertFileContainsNoInvalidStrings(pathname, strings) \
+ assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings)
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
@@ -182,6 +185,8 @@
assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
#define assertFileSize(pathname, size) \
assertion_file_size(__FILE__, __LINE__, pathname, size)
+#define assertFileMode(pathname, mode) \
+ assertion_file_mode(__FILE__, __LINE__, pathname, mode)
#define assertTextFileContents(text, pathname) \
assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
#define assertFileContainsLinesAnyOrder(pathname, lines) \
@@ -239,6 +244,7 @@ int assertion_file_atime_recent(const char *, int, const char *);
int assertion_file_birthtime(const char *, int, const char *, long, long);
int assertion_file_birthtime_recent(const char *, int, const char *);
int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
+int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **);
int assertion_file_contents(const char *, int, const void *, int, const char *);
int assertion_file_exists(const char *, int, const char *);
int assertion_file_mode(const char *, int, const char *, int);
diff --git a/contrib/libarchive/tar/test/test_missing_file.c b/contrib/libarchive/tar/test/test_missing_file.c
index e2e5da5..808e384 100644
--- a/contrib/libarchive/tar/test/test_missing_file.c
+++ b/contrib/libarchive/tar/test/test_missing_file.c
@@ -27,11 +27,15 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_missing_file)
{
+ const char * invalid_stderr[] = { "INTERNAL ERROR", NULL };
assertMakeFile("file1", 0644, "file1");
assertMakeFile("file2", 0644, "file2");
assert(0 == systemf("%s -cf archive.tar file1 file2 2>stderr1", testprog));
assertEmptyFile("stderr1");
assert(0 != systemf("%s -cf archive.tar file1 file2 file3 2>stderr2", testprog));
+ assertFileContainsNoInvalidStrings("stderr2", invalid_stderr);
assert(0 != systemf("%s -cf archive.tar 2>stderr3", testprog));
- assert(0 != systemf("%s -cf archive.tar file3 2>stderr4", testprog));
+ assertFileContainsNoInvalidStrings("stderr3", invalid_stderr);
+ assert(0 != systemf("%s -cf archive.tar file3 file4 2>stderr4", testprog));
+ assertFileContainsNoInvalidStrings("stderr4", invalid_stderr);
}
diff --git a/contrib/libarchive/tar/test/test_option_b.c b/contrib/libarchive/tar/test/test_option_b.c
index 81f50be..7c2f604 100644
--- a/contrib/libarchive/tar/test/test_option_b.c
+++ b/contrib/libarchive/tar/test/test_option_b.c
@@ -33,7 +33,7 @@ DEFINE_TEST(test_option_b)
assertMakeFile("file1", 0644, "file1");
if (systemf("cat file1 > test_cat.out 2> test_cat.err") != 0) {
- skipping("Platform doesn't have cat");
+ skipping("This test requires a `cat` program");
return;
}
testprog_ustar = malloc(strlen(testprog) + sizeof(USTAR_OPT) + 1);
diff --git a/contrib/libarchive/tar/test/test_symlink_dir.c b/contrib/libarchive/tar/test/test_symlink_dir.c
index 96bc3a4..ba643c2 100644
--- a/contrib/libarchive/tar/test/test_symlink_dir.c
+++ b/contrib/libarchive/tar/test/test_symlink_dir.c
@@ -63,7 +63,7 @@ DEFINE_TEST(test_symlink_dir)
/* "dir2" is a symlink to a non-existing "real_dir2" */
assertMakeSymlink("dest1/dir2", "real_dir2");
} else {
- skipping("some symlink checks");
+ skipping("Symlinks are not supported on this platform");
}
/* "dir3" is a symlink to an existing "non_dir3" */
assertMakeFile("dest1/non_dir3", 0755, "abcdef");
diff --git a/contrib/libucl/CMakeLists.txt b/contrib/libucl/CMakeLists.txt
index ae28a89..7b55faf 100644
--- a/contrib/libucl/CMakeLists.txt
+++ b/contrib/libucl/CMakeLists.txt
@@ -205,8 +205,7 @@ SET(UCLSRC src/ucl_util.c
src/ucl_hash.c
src/ucl_schema.c
src/ucl_msgpack.c
- src/ucl_sexp.c
- src/xxhash.c)
+ src/ucl_sexp.c)
SET (LIB_TYPE STATIC)
diff --git a/contrib/libucl/Makefile.unix b/contrib/libucl/Makefile.unix
index 121403d..0653d48 100644
--- a/contrib/libucl/Makefile.unix
+++ b/contrib/libucl/Makefile.unix
@@ -1,7 +1,7 @@
CC ?= gcc
DESTDIR ?= /usr/local
LD ?= gcc
-C_COMMON_FLAGS ?= -fPIC -Wall -W -Wno-unused-parameter -Wno-pointer-sign -I./include -I./uthash -I./src
+C_COMMON_FLAGS ?= -fPIC -Wall -W -Wno-unused-parameter -Wno-pointer-sign -I./include -I./uthash -I./src -I./klib
MAJOR_VERSION = 0
MINOR_VERSION = 2
PATCH_VERSION = 9
@@ -25,13 +25,12 @@ HDEPS = $(SRCDIR)/ucl_hash.h \
$(SRCDIR)/ucl_chartable.h \
$(SRCDIR)/ucl_internal.h \
$(INCLUDEDIR)/ucl.h \
- $(SRCDIR)/xxhash.h
+ $(SRCDIR)/mum.h
OBJECTS = $(OBJDIR)/ucl_hash.o \
$(OBJDIR)/ucl_util.o \
$(OBJDIR)/ucl_parser.o \
$(OBJDIR)/ucl_emitter.o \
- $(OBJDIR)/ucl_schema.o \
- $(OBJDIR)/xxhash.o
+ $(OBJDIR)/ucl_schema.o
all: $(OBJDIR) $(OBJDIR)/$(SONAME)
@@ -55,8 +54,6 @@ $(OBJDIR)/ucl_hash.o: $(SRCDIR)/ucl_hash.c $(HDEPS)
$(CC) -o $(OBJDIR)/ucl_hash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_hash.c
$(OBJDIR)/ucl_schema.o: $(SRCDIR)/ucl_schema.c $(HDEPS)
$(CC) -o $(OBJDIR)/ucl_schema.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_schema.c
-$(OBJDIR)/xxhash.o: $(SRCDIR)/xxhash.c $(HDEPS)
- $(CC) -o $(OBJDIR)/xxhash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/xxhash.c
clean:
$(RM) $(OBJDIR)/*.o $(OBJDIR)/$(SONAME_FULL) $(OBJDIR)/$(SONAME) $(OBJDIR)/chargen $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/objdump $(OBJDIR)/test_generate $(OBJDIR)/test_schema || true
diff --git a/contrib/libucl/Makefile.w32 b/contrib/libucl/Makefile.w32
index 0e61274..5d9398b 100644
--- a/contrib/libucl/Makefile.w32
+++ b/contrib/libucl/Makefile.w32
@@ -28,14 +28,13 @@ HDEPS = $(SRCDIR)/ucl_hash.h \
$(SRCDIR)/ucl_chartable.h \
$(SRCDIR)/ucl_internal.h \
$(INCLUDEDIR)/ucl.h \
- $(SRCDIR)/xxhash.h
+ $(SRCDIR)/mum.h
OBJECTS = $(OBJDIR)/ucl_hash.o \
$(OBJDIR)/ucl_util.o \
$(OBJDIR)/ucl_parser.o \
$(OBJDIR)/ucl_emitter.o \
$(OBJDIR)/ucl_emitter_utils.o \
- $(OBJDIR)/ucl_schema.o \
- $(OBJDIR)/xxhash.o
+ $(OBJDIR)/ucl_schema.o
all: $(OBJDIR) $(OBJDIR)/$(SONAME)
diff --git a/contrib/libucl/README.md b/contrib/libucl/README.md
index 0d76ca4..453a7ad 100644
--- a/contrib/libucl/README.md
+++ b/contrib/libucl/README.md
@@ -12,7 +12,7 @@
- [Named keys hierarchy](#named-keys-hierarchy)
- [Convenient numbers and booleans](#convenient-numbers-and-booleans)
- [General improvements](#general-improvements)
- - [Commments](#commments)
+ - [Comments](#comments)
- [Macros support](#macros-support)
- [Variables support](#variables-support)
- [Multiline strings](#multiline-strings)
@@ -21,7 +21,7 @@
- [Performance](#performance)
- [Conclusion](#conclusion)
-## Introduction
+## Introduction
This document describes the main features and principles of the configuration
language called `UCL` - universal configuration language.
@@ -47,7 +47,7 @@ section {
string = "something";
subsection {
host = {
- host = "hostname";
+ host = "hostname";
port = 900;
}
host = {
@@ -163,9 +163,9 @@ section {
}
}
```
-
+
Plain definitions may be more complex and contain more than a single level of nested objects:
-
+
```nginx
section "blah" "foo" {
key = value;
@@ -174,7 +174,7 @@ section "blah" "foo" {
is presented as:
-```nginx
+```nginx
section {
blah {
foo {
@@ -196,17 +196,17 @@ section {
## General improvements
-### Commments
+### Comments
UCL supports different style of comments:
-* single line: `#`
+* single line: `#`
* multiline: `/* ... */`
Multiline comments may be nested:
```c
# Sample single line comment
-/*
+/*
some comment
/* nested comment */
end of comment
@@ -263,7 +263,7 @@ all files that matches the specified pattern (normally the format of patterns is
for your operating system). This option is meaningless for URL includes.
* `url` (default: **true**) - allow URL includes.
* `path` (default: empty) - A UCL_ARRAY of directories to search for the include file.
-Search ends after the first patch, unless `glob` is true, then all matches are included.
+Search ends after the first match, unless `glob` is true, then all matches are included.
* `prefix` (default false) - Put included contents inside an object, instead
of loading them into the root. If no `key` is provided, one is automatically generated based on each files basename()
* `key` (default: <empty string>) - Key to load contents of include into. If
@@ -273,7 +273,7 @@ object or an array.
* `priority` (default: 0) - specify priority for the include (see below).
* `duplicate` (default: 'append') - specify policy of duplicates resolving:
- `append` - default strategy, if we have new object of higher priority then it replaces old one, if we have new object with less priority it is ignored completely, and if we have two duplicate objects with the same priority then we have a multi-value key (implicit array)
- - `merge` - if we have object or array, then new keys are merged inside, if we have a plain object then an implicit array is formed (regardeless of priorities)
+ - `merge` - if we have object or array, then new keys are merged inside, if we have a plain object then an implicit array is formed (regardless of priorities)
- `error` - create error on duplicate keys and stop parsing
- `rewrite` - always rewrite an old value with new one (ignoring priorities)
@@ -320,7 +320,7 @@ Here are some rules for this syntax:
* Multiline terminator must start just after `<<` symbols and it must consist of capital letters only (e.g. `<<eof` or `<< EOF` won't work);
* Terminator must end with a single newline character (and no spaces are allowed between terminator and newline character);
* To finish multiline string you need to include a terminator string just after newline and followed by a newline (no spaces or other characters are allowed as well);
-* The initial and the final newlines are not inserted to the resulting string, but you can still specify newlines at the begin and at the end of a value, for example:
+* The initial and the final newlines are not inserted to the resulting string, but you can still specify newlines at the beginning and at the end of a value, for example:
```
key <<EOD
@@ -347,7 +347,7 @@ UCL allows validation of objects. It uses the same schema that is used for json:
## Performance
Are UCL parser and emitter fast enough? Well, there are some numbers.
-I got a 19Mb file that consist of ~700 thousands lines of json (obtained via
+I got a 19Mb file that consist of ~700 thousand lines of json (obtained via
http://www.json-generator.com/). Then I checked jansson library that performs json
parsing and emitting and compared it with UCL. Here are results:
@@ -377,6 +377,6 @@ You can do your own benchmarks by running `make check` in libucl top directory.
## Conclusion
UCL has clear design that should be very convenient for reading and writing. At the same time it is compatible with
-JSON language and therefore can be used as a simple JSON parser. Macroes logic provides an ability to extend configuration
-language (for example by including some lua code) and comments allows to disable or enable the parts of a configuration
+JSON language and therefore can be used as a simple JSON parser. Macro logic provides an ability to extend configuration
+language (for example by including some lua code) and comments allow to disable or enable the parts of a configuration
quickly.
diff --git a/contrib/libucl/haskell/hucl.hs b/contrib/libucl/haskell/hucl.hs
new file mode 100644
index 0000000..2dd3ac0
--- /dev/null
+++ b/contrib/libucl/haskell/hucl.hs
@@ -0,0 +1,123 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+-- an example UCL FFI module:
+-- uses the Object Model from Messagepack to emit
+--
+
+module Data.UCL ( unpack ) where
+import Foreign.C
+import Foreign.Ptr
+import System.IO.Unsafe ( unsafePerformIO )
+import qualified Data.Text as T
+import qualified Data.Vector as V
+import qualified Data.MessagePack as MSG
+
+type ParserHandle = Ptr ()
+type UCLObjectHandle = Ptr ()
+type UCLIterHandle = Ptr ()
+type UCLEmitterType = CInt
+type ErrorString = String
+
+
+foreign import ccall "ucl_parser_new" ucl_parser_new :: CInt -> ParserHandle
+foreign import ccall "ucl_parser_add_string" ucl_parser_add_string :: ParserHandle -> CString -> CUInt -> IO Bool
+foreign import ccall "ucl_parser_add_file" ucl_parser_add_file :: ParserHandle -> CString -> IO Bool
+foreign import ccall "ucl_parser_get_object" ucl_parser_get_object :: ParserHandle -> UCLObjectHandle
+foreign import ccall "ucl_parser_get_error" ucl_parser_get_error :: ParserHandle -> CString
+
+foreign import ccall "ucl_object_iterate_new" ucl_object_iterate_new :: UCLObjectHandle -> UCLIterHandle
+foreign import ccall "ucl_object_iterate_safe" ucl_object_iterate_safe :: UCLIterHandle -> Bool -> UCLObjectHandle
+foreign import ccall "ucl_object_type" ucl_object_type :: UCLObjectHandle -> CUInt
+foreign import ccall "ucl_object_key" ucl_object_key :: UCLObjectHandle -> CString
+foreign import ccall "ucl_object_toint" ucl_object_toint :: UCLObjectHandle -> CInt
+foreign import ccall "ucl_object_todouble" ucl_object_todouble :: UCLObjectHandle -> CDouble
+foreign import ccall "ucl_object_tostring" ucl_object_tostring :: UCLObjectHandle -> CString
+foreign import ccall "ucl_object_toboolean" ucl_object_toboolean :: UCLObjectHandle -> Bool
+
+foreign import ccall "ucl_object_emit" ucl_object_emit :: UCLObjectHandle -> UCLEmitterType -> CString
+foreign import ccall "ucl_object_emit_len" ucl_object_emit_len :: UCLObjectHandle -> UCLEmitterType -> Ptr CSize -> IO CString
+
+type UCL_TYPE = CUInt
+ucl_OBJECT :: UCL_TYPE
+ucl_OBJECT = 0
+ucl_ARRAY :: UCL_TYPE
+ucl_ARRAY = 1
+ucl_INT :: UCL_TYPE
+ucl_INT = 2
+ucl_FLOAT :: UCL_TYPE
+ucl_FLOAT = 3
+ucl_STRING :: UCL_TYPE
+ucl_STRING = 4
+ucl_BOOLEAN :: UCL_TYPE
+ucl_BOOLEAN = 5
+ucl_TIME :: UCL_TYPE
+ucl_TIME = 6
+ucl_USERDATA :: UCL_TYPE
+ucl_USERDATA = 7
+ucl_NULL :: UCL_TYPE
+ucl_NULL = 8
+
+ucl_emit_json :: UCLEmitterType
+ucl_emit_json = 0
+ucl_emit_json_compact :: UCLEmitterType
+ucl_emit_json_compact = 1 :: UCLEmitterType
+ucl_emit_msgpack :: UCLEmitterType
+ucl_emit_msgpack = 4 :: UCLEmitterType
+
+ucl_parser_parse_string_pure :: String -> Either UCLObjectHandle ErrorString
+ucl_parser_parse_string_pure s = unsafePerformIO $ do
+ cs <- newCString s
+ let p = ucl_parser_new 0x4
+ didParse <- ucl_parser_add_string p cs (toEnum $ length s)
+ if didParse
+ then return $ Left $ ucl_parser_get_object p
+ else Right <$> peekCString ( ucl_parser_get_error p)
+
+ucl_parser_add_file_pure :: String -> Either UCLObjectHandle ErrorString
+ucl_parser_add_file_pure s = unsafePerformIO $ do
+ cs <- newCString s
+ let p = ucl_parser_new 0x4
+ didParse <- ucl_parser_add_file p cs
+ if didParse
+ then return $ Left $ ucl_parser_get_object p
+ else Right <$> peekCString ( ucl_parser_get_error p)
+
+unpack :: MSG.MessagePack a => String -> Either a ErrorString
+unpack s = case ucl_parser_parse_string_pure s of
+ (Right err) -> Right err
+ (Left obj) -> case MSG.fromObject (ucl_to_msgpack_object obj) of
+ Nothing -> Right "MessagePack fromObject Error"
+ (Just a) -> Left a
+
+ucl_to_msgpack_object :: UCLObjectHandle -> MSG.Object
+ucl_to_msgpack_object o = toMsgPackObj (ucl_object_type o) o
+ where
+ toMsgPackObj n obj
+ |n==ucl_OBJECT = MSG.ObjectMap $ uclObjectToVector obj
+ |n==ucl_ARRAY = MSG.ObjectArray undefined
+ |n==ucl_INT = MSG.ObjectInt $ fromEnum $ ucl_object_toint obj
+ |n==ucl_FLOAT = MSG.ObjectDouble $ realToFrac $ ucl_object_todouble obj
+ |n==ucl_STRING = MSG.ObjectStr $ T.pack $ unsafePerformIO $ peekCString $ ucl_object_tostring obj
+ |n==ucl_BOOLEAN = MSG.ObjectBool $ ucl_object_toboolean obj
+ |n==ucl_TIME = error "time undefined"
+ |n==ucl_USERDATA = error "userdata undefined"
+ |n==ucl_NULL = error "null undefined"
+ |otherwise = error "\"Unknown Type\" Error"
+
+uclObjectToVector :: UCLObjectHandle -> V.Vector (MSG.Object,MSG.Object)
+uclObjectToVector o = iterateObject (ucl_object_iterate_safe iter True ) iter V.empty
+ where
+ iter = ucl_object_iterate_new o
+ iterateObject obj it vec = if ucl_object_type obj == ucl_NULL
+ then vec
+ else iterateObject (ucl_object_iterate_safe it True) it (V.snoc vec ( getUclKey obj , ucl_to_msgpack_object obj))
+ getUclKey obj = MSG.ObjectStr $ T.pack $ unsafePerformIO $ peekCString $ ucl_object_key obj
+
+uclArrayToVector :: UCLObjectHandle -> V.Vector MSG.Object
+uclArrayToVector o = iterateArray (ucl_object_iterate_safe iter True ) iter V.empty
+ where
+ iter = ucl_object_iterate_new o
+ iterateArray obj it vec = if ucl_object_type obj == ucl_NULL
+ then vec
+ else iterateArray (ucl_object_iterate_safe it True) it (V.snoc vec (ucl_to_msgpack_object obj))
+
diff --git a/contrib/libucl/include/ucl++.h b/contrib/libucl/include/ucl++.h
index 00297e7..2c2bdde 100644
--- a/contrib/libucl/include/ucl++.h
+++ b/contrib/libucl/include/ucl++.h
@@ -24,6 +24,9 @@
#pragma once
#include <string>
+#include <vector>
+#include <map>
+#include <set>
#include <memory>
#include <iostream>
@@ -100,6 +103,68 @@ private:
return func;
};
+ static bool ucl_variable_getter(const unsigned char *data, size_t len,
+ unsigned char ** /*replace*/, size_t * /*replace_len*/, bool *need_free, void* ud)
+ {
+ *need_free = false;
+
+ auto vars = reinterpret_cast<std::set<std::string> *>(ud);
+ if (vars && data && len != 0) {
+ vars->emplace (data, data + len);
+ }
+ return false;
+ }
+
+ static bool ucl_variable_replacer (const unsigned char *data, size_t len,
+ unsigned char **replace, size_t *replace_len, bool *need_free, void* ud)
+ {
+ *need_free = false;
+
+ auto replacer = reinterpret_cast<variable_replacer *>(ud);
+ if (!replacer) {
+ return false;
+ }
+
+ std::string var_name (data, data + len);
+ if (!replacer->is_variable (var_name)) {
+ return false;
+ }
+
+ std::string var_value = replacer->replace (var_name);
+ if (var_value.empty ()) {
+ return false;
+ }
+
+ *replace = (unsigned char *)UCL_ALLOC (var_value.size ());
+ memcpy (*replace, var_value.data (), var_value.size ());
+
+ *replace_len = var_value.size ();
+ *need_free = true;
+
+ return true;
+ }
+
+ template <typename C, typename P>
+ static Ucl parse_with_strategy_function (C config_func, P parse_func, std::string &err)
+ {
+ auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
+
+ config_func (parser);
+
+ if (!parse_func (parser)) {
+ err.assign (ucl_parser_get_error (parser));
+ ucl_parser_free (parser);
+
+ return nullptr;
+ }
+
+ auto obj = ucl_parser_get_object (parser);
+ ucl_parser_free (parser);
+
+ // Obj will handle ownership
+ return Ucl (obj);
+ }
+
std::unique_ptr<ucl_object_t, ucl_deleter> obj;
public:
@@ -117,9 +182,9 @@ public:
const_iterator(const Ucl &obj) {
it = std::shared_ptr<void>(ucl_object_iterate_new (obj.obj.get()),
- ucl_iter_deleter());
+ ucl_iter_deleter());
cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
- if (!*cur) {
+ if (cur->type() == UCL_NULL) {
it.reset ();
cur.reset ();
}
@@ -153,7 +218,7 @@ public:
cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
}
- if (!*cur) {
+ if (cur && cur->type() == UCL_NULL) {
it.reset ();
cur.reset ();
}
@@ -171,6 +236,17 @@ public:
}
};
+ struct variable_replacer {
+ virtual ~variable_replacer() {}
+
+ virtual bool is_variable (const std::string &str) const
+ {
+ return !str.empty ();
+ }
+
+ virtual std::string replace (const std::string &var) const = 0;
+ };
+
// We grab ownership if get non-const ucl_object_t
Ucl(ucl_object_t *other) {
obj.reset (other);
@@ -211,20 +287,20 @@ public:
obj.reset (ucl_object_fromstring_common (value.data (), value.size (),
UCL_STRING_RAW));
}
- Ucl(const char * value) {
+ Ucl(const char *value) {
obj.reset (ucl_object_fromstring_common (value, 0, UCL_STRING_RAW));
}
// Implicit constructor: anything with a to_json() function.
template <class T, class = decltype(&T::to_ucl)>
- Ucl(const T & t) : Ucl(t.to_ucl()) {}
+ Ucl(const T &t) : Ucl(t.to_ucl()) {}
// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
template <class M, typename std::enable_if<
std::is_constructible<std::string, typename M::key_type>::value
&& std::is_constructible<Ucl, typename M::mapped_type>::value,
int>::type = 0>
- Ucl(const M & m) {
+ Ucl(const M &m) {
obj.reset (ucl_object_typed_new (UCL_OBJECT));
auto cobj = obj.get ();
@@ -238,7 +314,7 @@ public:
template <class V, typename std::enable_if<
std::is_constructible<Ucl, typename V::value_type>::value,
int>::type = 0>
- Ucl(const V & v) {
+ Ucl(const V &v) {
obj.reset (ucl_object_typed_new (UCL_ARRAY));
auto cobj = obj.get ();
@@ -356,46 +432,138 @@ public:
return out;
}
- static Ucl parse (const std::string & in, std::string & err)
+ static Ucl parse (const std::string &in, std::string &err)
{
- auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
+ return parse (in, std::map<std::string, std::string>(), err);
+ }
- if (!ucl_parser_add_chunk (parser, (const unsigned char *)in.data (),
- in.size ())) {
- err.assign (ucl_parser_get_error (parser));
- ucl_parser_free (parser);
+ static Ucl parse (const std::string &in, const std::map<std::string, std::string> &vars, std::string &err)
+ {
+ auto config_func = [&vars] (ucl_parser *parser) {
+ for (const auto & item : vars) {
+ ucl_parser_register_variable (parser, item.first.c_str (), item.second.c_str ());
+ }
+ };
+
+ auto parse_func = [&in] (ucl_parser *parser) {
+ return ucl_parser_add_chunk (parser, (unsigned char *)in.data (), in.size ());
+ };
+
+ return parse_with_strategy_function (config_func, parse_func, err);
+ }
+ static Ucl parse (const std::string &in, const variable_replacer &replacer, std::string &err)
+ {
+ auto config_func = [&replacer] (ucl_parser *parser) {
+ ucl_parser_set_variables_handler (parser, ucl_variable_replacer,
+ &const_cast<variable_replacer &>(replacer));
+ };
+
+ auto parse_func = [&in] (ucl_parser *parser) {
+ return ucl_parser_add_chunk (parser, (unsigned char *) in.data (), in.size ());
+ };
+
+ return parse_with_strategy_function (config_func, parse_func, err);
+ }
+
+ static Ucl parse (const char *in, std::string &err)
+ {
+ return parse (in, std::map<std::string, std::string>(), err);
+ }
+
+ static Ucl parse (const char *in, const std::map<std::string, std::string> &vars, std::string &err)
+ {
+ if (!in) {
+ err = "null input";
return nullptr;
}
+ return parse (std::string (in), vars, err);
+ }
- auto obj = ucl_parser_get_object (parser);
+ static Ucl parse (const char *in, const variable_replacer &replacer, std::string &err)
+ {
+ if (!in) {
+ err = "null input";
+ return nullptr;
+ }
+ return parse (std::string(in), replacer, err);
+ }
+
+ static Ucl parse_from_file (const std::string &filename, std::string &err)
+ {
+ return parse_from_file (filename, std::map<std::string, std::string>(), err);
+ }
+
+ static Ucl parse_from_file (const std::string &filename, const std::map<std::string, std::string> &vars, std::string &err)
+ {
+ auto config_func = [&vars] (ucl_parser *parser) {
+ for (const auto & item : vars) {
+ ucl_parser_register_variable (parser, item.first.c_str (), item.second.c_str ());
+ }
+ };
+
+ auto parse_func = [&filename] (ucl_parser *parser) {
+ return ucl_parser_add_file (parser, filename.c_str ());
+ };
+
+ return parse_with_strategy_function (config_func, parse_func, err);
+ }
+
+ static Ucl parse_from_file (const std::string &filename, const variable_replacer &replacer, std::string &err)
+ {
+ auto config_func = [&replacer] (ucl_parser *parser) {
+ ucl_parser_set_variables_handler (parser, ucl_variable_replacer,
+ &const_cast<variable_replacer &>(replacer));
+ };
+
+ auto parse_func = [&filename] (ucl_parser *parser) {
+ return ucl_parser_add_file (parser, filename.c_str ());
+ };
+
+ return parse_with_strategy_function (config_func, parse_func, err);
+ }
+
+ static std::vector<std::string> find_variable (const std::string &in)
+ {
+ auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
+
+ std::set<std::string> vars;
+ ucl_parser_set_variables_handler (parser, ucl_variable_getter, &vars);
+ ucl_parser_add_chunk (parser, (const unsigned char *)in.data (), in.size ());
ucl_parser_free (parser);
- // Obj will handle ownership
- return Ucl (obj);
+ std::vector<std::string> result;
+ std::move (vars.begin (), vars.end (), std::back_inserter (result));
+ return result;
}
- static Ucl parse (const char * in, std::string & err)
+ static std::vector<std::string> find_variable (const char *in)
{
- if (in) {
- return parse (std::string(in), err);
- } else {
- err = "null input";
- return nullptr;
+ if (!in) {
+ return std::vector<std::string>();
}
+ return find_variable (std::string (in));
}
- static Ucl parse (std::istream &ifs, std::string &err)
+ static std::vector<std::string> find_variable_from_file (const std::string &filename)
{
- return Ucl::parse (std::string(std::istreambuf_iterator<char>(ifs),
- std::istreambuf_iterator<char>()), err);
+ auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
+
+ std::set<std::string> vars;
+ ucl_parser_set_variables_handler (parser, ucl_variable_getter, &vars);
+ ucl_parser_add_file (parser, filename.c_str ());
+ ucl_parser_free (parser);
+
+ std::vector<std::string> result;
+ std::move (vars.begin (), vars.end (), std::back_inserter (result));
+ return std::move (result);
}
- Ucl& operator= (Ucl rhs)
- {
- obj.swap (rhs.obj);
- return *this;
- }
+ Ucl& operator= (Ucl rhs)
+ {
+ obj.swap (rhs.obj);
+ return *this;
+ }
bool operator== (const Ucl &rhs) const
{
diff --git a/contrib/libucl/include/ucl.h b/contrib/libucl/include/ucl.h
index 024f5dd..304d329 100644
--- a/contrib/libucl/include/ucl.h
+++ b/contrib/libucl/include/ucl.h
@@ -1016,7 +1016,6 @@ UCL_EXTERN bool ucl_parser_add_string_priority (struct ucl_parser *parser,
* Load and add data from a file
* @param parser parser structure
* @param filename the name of file
- * @param err if *err is NULL it is set to parser error
* @return true if chunk has been added and false in case of error
*/
UCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser,
@@ -1026,7 +1025,6 @@ UCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser,
* Load and add data from a file
* @param parser parser structure
* @param filename the name of file
- * @param err if *err is NULL it is set to parser error
* @param priority the desired priority of a chunk (only 4 least significant bits
* are considered for this parameter)
* @return true if chunk has been added and false in case of error
@@ -1035,6 +1033,20 @@ UCL_EXTERN bool ucl_parser_add_file_priority (struct ucl_parser *parser,
const char *filename, unsigned priority);
/**
+ * Load and add data from a file
+ * @param parser parser structure
+ * @param filename the name of file
+ * @param priority the desired priority of a chunk (only 4 least significant bits
+ * are considered for this parameter)
+ * @param strat Merge strategy to use while parsing this file
+ * @param parse_type Parser type to use while parsing this file
+ * @return true if chunk has been added and false in case of error
+ */
+UCL_EXTERN bool ucl_parser_add_file_full (struct ucl_parser *parser, const char *filename,
+ unsigned priority, enum ucl_duplicate_strategy strat,
+ enum ucl_parse_type parse_type);
+
+/**
* Load and add data from a file descriptor
* @param parser parser structure
* @param filename the name of file
diff --git a/contrib/libucl/m4/gcov.m4 b/contrib/libucl/m4/gcov.m4
new file mode 100644
index 0000000..a1359a0
--- /dev/null
+++ b/contrib/libucl/m4/gcov.m4
@@ -0,0 +1,89 @@
+# SYNOPSIS
+#
+# Add code coverage support with gcov/lcov.
+#
+# AX_CODE_COVERAGE()
+#
+# DESCRIPTION
+#
+# Provides a --enable-coverage option which checks for available
+# gcov/lcov binaries and provides ENABLE_CODE_COVERAGE conditional.
+#
+# LAST MODIFICATION
+#
+# $Id: coverage.m4 40881 2013-08-20 17:54:39Z damon $
+#
+# COPYLEFT
+#
+# Copyright (c) 2012 Roy H. Stogner <roystgnr@ices.utexas.edu>
+# Copyright (c) 2010 Karl W. Schulz <karl@ices.utexas.edu>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved.
+
+AC_DEFUN([AX_CODE_COVERAGE],
+[
+
+AC_ARG_ENABLE(coverage, AC_HELP_STRING([--enable-coverage],[configure code coverage analysis tools]))
+
+HAVE_GCOV_TOOLS=0
+
+GCOV_FLAGS=""
+
+if test "x$enable_coverage" = "xyes"; then
+
+ # ----------------------------
+ # Check for gcov/lcov binaries
+ # ----------------------------
+
+ AC_ARG_VAR([GCOV], [Coverage testing command])
+ if test "x$GCOV" = "x"; then
+ AC_PATH_PROG(GCOV, gcov, no)
+ else
+ AC_PATH_PROG(GCOV, $GCOV, no)
+ fi
+
+ AC_PATH_PROG(LCOV, lcov, no)
+ AC_PATH_PROG(GENHTML, genhtml)
+
+ # ----------------------------------
+ # include coverage compiler options
+ # ----------------------------------
+ AC_MSG_CHECKING([for clang])
+
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([], [[
+ #ifndef __clang__
+ not clang
+ #endif
+ ]])],
+ [CLANG=yes], [CLANG=no])
+
+ AC_MSG_RESULT([$CLANG])
+ HAVE_GCOV_TOOLS=1
+ COVERAGE_CFLAGS="-fprofile-arcs -ftest-coverage"
+ COVERAGE_LDFLAGS="--coverage -fprofile-arcs -ftest-coverage"
+ COVERAGE_OPTFLAGS="-O0"
+
+ # Test for C...
+ CFLAGS="${GCOV_FLAGS} ${CFLAGS}"
+ CXXFLAGS="${GCOV_FLAGS} ${CXXFLAGS}"
+ if test "x$GCC" = "xyes" -a "x$CLANG" = "xno"; then
+ COVERAGE_LIBS="-lgcov"
+ else
+ COVERAGE_LIBS=""
+ fi
+fi
+
+AC_SUBST([GCOV])
+AC_SUBST([LCOV])
+AC_SUBST([GENHTML])
+AC_SUBST([GENHTML_OPTIONS])
+AC_SUBST([COVERAGE_CFLAGS])
+AC_SUBST([COVERAGE_OPTFLAGS])
+AC_SUBST([COVERAGE_LDFLAGS])
+AC_SUBST([COVERAGE_LIBS])
+AM_CONDITIONAL(CODE_COVERAGE_ENABLED,test x$HAVE_GCOV_TOOLS = x1)
+
+])
diff --git a/contrib/libucl/python/setup.py b/contrib/libucl/python/setup.py
index b2b8981..9e1151a 100644
--- a/contrib/libucl/python/setup.py
+++ b/contrib/libucl/python/setup.py
@@ -1,37 +1,43 @@
-import distutils.ccompiler
-import distutils.sysconfig
-from distutils.core import setup, Extension
+try:
+ from setuptools import setup, Extension
+except ImportError:
+ from distutils.core import setup, Extension
+
import os
+import sys
+tests_require = []
-compiler = distutils.ccompiler.new_compiler()
-search_paths=[os.path.expanduser('~/{}'), '/opt/local/{}', '/usr/local/{}', '/usr/{}']
-lib_paths = [ a.format("lib") for a in search_paths]
-inc_paths = [ a.format("include") for a in search_paths]
+if sys.version < '2.7':
+ tests_require.append('unittest2')
-uclmodule = Extension('ucl',
- include_dirs = inc_paths,
- library_dirs = lib_paths,
- libraries = ['ucl'],
- sources = ['src/uclmodule.c'],
- runtime_library_dirs = lib_paths,
- language='c')
+uclmodule = Extension(
+ 'ucl',
+ libraries = ['ucl'],
+ sources = ['src/uclmodule.c'],
+ language = 'c'
+)
-setup(name='ucl',
- version='1.0',
- description='ucl parser and emmitter',
+setup(
+ name = 'ucl',
+ version = '0.8',
+ description = 'ucl parser and emmitter',
ext_modules = [uclmodule],
- author="Eitan Adler",
- author_email="lists@eitanadler.com",
- url="https://github.com/vstakhov/libucl/",
- license="MIT",
- classifiers=["Development Status :: 3 - Alpha",
+ test_suite = 'tests',
+ tests_require = tests_require,
+ author = "Eitan Adler, Denis Volpato Martins",
+ author_email = "lists@eitanadler.com",
+ url = "https://github.com/vstakhov/libucl/",
+ license = "MIT",
+ classifiers = [
+ "Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: DFSG approved",
"License :: OSI Approved :: MIT License",
"Programming Language :: C",
+ "Programming Language :: Python :: 2",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: Implementation :: CPython",
"Topic :: Software Development :: Libraries",
- ]
- )
+ ]
+)
diff --git a/contrib/libucl/python/src/uclmodule.c b/contrib/libucl/python/src/uclmodule.c
index bc13c70..fce0dab 100644
--- a/contrib/libucl/python/src/uclmodule.c
+++ b/contrib/libucl/python/src/uclmodule.c
@@ -2,6 +2,8 @@
#include <ucl.h>
#include <Python.h>
+static PyObject *SchemaError;
+
static PyObject *
_basic_ucl_type (ucl_object_t const *obj)
{
@@ -13,9 +15,11 @@ _basic_ucl_type (ucl_object_t const *obj)
case UCL_STRING:
return Py_BuildValue ("s", ucl_object_tostring (obj));
case UCL_BOOLEAN:
- return ucl_object_toboolean (obj) ? Py_True : Py_False;
+ return PyBool_FromLong (ucl_object_toboolean (obj));
case UCL_TIME:
return Py_BuildValue ("d", ucl_object_todouble (obj));
+ case UCL_NULL:
+ Py_RETURN_NONE;
}
return NULL;
}
@@ -124,26 +128,60 @@ _iterate_python (PyObject *obj)
{
if (obj == Py_None) {
return ucl_object_new();
- } else if (PyBool_Check (obj)) {
+ }
+ else if (PyBool_Check (obj)) {
return ucl_object_frombool (obj == Py_True);
- } else if (PyInt_Check (obj)) {
+ }
+#if PY_MAJOR_VERSION < 3
+ else if (PyInt_Check (obj)) {
return ucl_object_fromint (PyInt_AsLong (obj));
- } else if (PyFloat_Check (obj)) {
+ }
+#endif
+ else if (PyLong_Check (obj)) {
+ return ucl_object_fromint (PyLong_AsLong (obj));
+ }
+ else if (PyFloat_Check (obj)) {
return ucl_object_fromdouble (PyFloat_AsDouble (obj));
- } else if (PyString_Check (obj)) {
+ }
+ else if (PyUnicode_Check (obj)) {
+ ucl_object_t *ucl_str;
+ PyObject *str = PyUnicode_AsASCIIString(obj);
+ ucl_str = ucl_object_fromstring (PyBytes_AsString (str));
+ Py_DECREF(str);
+ return ucl_str;
+ }
+#if PY_MAJOR_VERSION < 3
+ else if (PyString_Check (obj)) {
return ucl_object_fromstring (PyString_AsString (obj));
- // } else if (PyDateTime_Check (obj)) {
}
+#endif
else if (PyDict_Check(obj)) {
PyObject *key, *value;
Py_ssize_t pos = 0;
ucl_object_t *top, *elm;
+ char *keystr = NULL;
top = ucl_object_typed_new (UCL_OBJECT);
while (PyDict_Next(obj, &pos, &key, &value)) {
elm = _iterate_python(value);
- ucl_object_insert_key (top, elm, PyString_AsString(key), 0, true);
+
+ if (PyUnicode_Check(key)) {
+ PyObject *keyascii = PyUnicode_AsASCIIString(key);
+ keystr = PyBytes_AsString(keyascii);
+ Py_DECREF(keyascii);
+ }
+#if PY_MAJOR_VERSION < 3
+ else if (PyString_Check(key)) {
+ keystr = PyString_AsString(key);
+ }
+#endif
+ else {
+ PyErr_SetString(PyExc_TypeError, "Unknown key type");
+ return NULL;
+ }
+
+ ucl_object_insert_key (top, elm, keystr, 0, true);
}
return top;
@@ -195,11 +233,6 @@ ucl_dump (PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
- if (!PyDict_Check(obj)) {
- PyErr_SetString(PyExc_TypeError, "Argument must be dict");
- return NULL;
- }
-
root = _iterate_python(obj);
if (root) {
PyObject *ret;
@@ -207,7 +240,11 @@ ucl_dump (PyObject *self, PyObject *args)
buf = (char *) ucl_object_emit (root, emitter);
ucl_object_unref (root);
+#if PY_MAJOR_VERSION < 3
ret = PyString_FromString (buf);
+#else
+ ret = PyUnicode_FromString (buf);
+#endif
free(buf);
return ret;
@@ -219,17 +256,35 @@ ucl_dump (PyObject *self, PyObject *args)
static PyObject *
ucl_validate (PyObject *self, PyObject *args)
{
- char *uclstr, *schema;
+ PyObject *dataobj, *schemaobj;
+ ucl_object_t *data, *schema;
+ bool r;
+ struct ucl_schema_error err;
- if (PyArg_ParseTuple(args, "zz", &uclstr, &schema)) {
- if (!uclstr || !schema) {
- Py_RETURN_NONE;
- }
+ if (!PyArg_ParseTuple (args, "OO", &schemaobj, &dataobj)) {
+ PyErr_SetString (PyExc_TypeError, "Unhandled object type");
+ return NULL;
+ }
- PyErr_SetString(PyExc_NotImplementedError, "schema validation is not yet supported");
+ schema = _iterate_python(schemaobj);
+ if (!schema)
+ return NULL;
+
+ data = _iterate_python(dataobj);
+ if (!data)
+ return NULL;
+
+ // validation
+ r = ucl_object_validate (schema, data, &err);
+ ucl_object_unref (schema);
+ ucl_object_unref (data);
+
+ if (!r) {
+ PyErr_SetString (SchemaError, err.msg);
+ return NULL;
}
- return NULL;
+ Py_RETURN_TRUE;
}
static PyMethodDef uclMethods[] = {
@@ -247,6 +302,10 @@ init_macros(PyObject *mod)
PyModule_AddIntMacro(mod, UCL_EMIT_CONFIG);
PyModule_AddIntMacro(mod, UCL_EMIT_YAML);
PyModule_AddIntMacro(mod, UCL_EMIT_MSGPACK);
+
+ SchemaError = PyErr_NewException("ucl.SchemaError", NULL, NULL);
+ Py_INCREF(SchemaError);
+ PyModule_AddObject(mod, "SchemaError", SchemaError);
}
#if PY_MAJOR_VERSION >= 3
diff --git a/contrib/libucl/python/test.sh b/contrib/libucl/python/test.sh
deleted file mode 100755
index 53af6a3..0000000
--- a/contrib/libucl/python/test.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-set -xe
-python3.4 setup.py build_ext --inplace
-./test_uclmodule.py -v
-rm -rfv build
-rm ucl.so
diff --git a/contrib/libucl/python/test_uclmodule.py b/contrib/libucl/python/test_uclmodule.py
deleted file mode 100755
index 0d77469..0000000
--- a/contrib/libucl/python/test_uclmodule.py
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/env python
-import json
-import unittest
-import ucl
-import sys
-
-if sys.version_info[:2] == (2, 7):
- unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
-
-
-class TestUcl(unittest.TestCase):
- def test_no_args(self):
- with self.assertRaises(TypeError):
- ucl.load()
-
- def test_multi_args(self):
- with self.assertRaises(TypeError):
- ucl.load(0,0)
-
- def test_none(self):
- r = ucl.load(None)
- self.assertEqual(r, None)
-
- def test_int(self):
- r = ucl.load("a : 1")
- self.assertEqual(ucl.load("a : 1"), { "a" : 1 } )
-
- def test_braced_int(self):
- self.assertEqual(ucl.load("{a : 1}"), { "a" : 1 } )
-
- def test_nested_int(self):
- self.assertEqual(ucl.load("a : { b : 1 }"), { "a" : { "b" : 1 } })
-
- def test_str(self):
- self.assertEqual(ucl.load("a : b"), {"a" : "b"})
-
- def test_float(self):
- self.assertEqual(ucl.load("a : 1.1"), {"a" : 1.1})
-
- def test_boolean(self):
- totest = (
- "a : True;" \
- "b : False"
- )
- correct = {"a" : True, "b" : False}
- self.assertEqual(ucl.load(totest), correct)
-
- def test_empty_ucl(self):
- r = ucl.load("{}")
- self.assertEqual(r, {})
-
- def test_single_brace(self):
- self.assertEqual(ucl.load("{"), {})
-
- def test_single_back_brace(self):
- ucl.load("}")
-
- def test_single_square_forward(self):
- self.assertEqual(ucl.load("["), [])
-
- def test_invalid_ucl(self):
- with self.assertRaisesRegex(ValueError, "unfinished key$"):
- ucl.load('{ "var"')
-
- def test_comment_ignored(self):
- self.assertEqual(ucl.load("{/*1*/}"), {})
-
- def test_1_in(self):
- with open("../tests/basic/1.in", "r") as in1:
- self.assertEqual(ucl.load(in1.read()), {'key1': 'value'})
-
- def test_every_type(self):
- totest="""{
- "key1": value;
- "key2": value2;
- "key3": "value;"
- "key4": 1.0,
- "key5": -0xdeadbeef
- "key6": 0xdeadbeef.1
- "key7": 0xreadbeef
- "key8": -1e-10,
- "key9": 1
- "key10": true
- "key11": no
- "key12": yes
- }"""
- correct = {
- 'key1': 'value',
- 'key2': 'value2',
- 'key3': 'value;',
- 'key4': 1.0,
- 'key5': -3735928559,
- 'key6': '0xdeadbeef.1',
- 'key7': '0xreadbeef',
- 'key8': -1e-10,
- 'key9': 1,
- 'key10': True,
- 'key11': False,
- 'key12': True,
- }
- self.assertEqual(ucl.load(totest), correct)
-
- def test_validation_useless(self):
- with self.assertRaises(NotImplementedError):
- ucl.validate("","")
-
-
-class TestUclDump(unittest.TestCase):
- def test_no_args(self):
- with self.assertRaises(TypeError):
- ucl.dump()
-
- def test_multi_args(self):
- with self.assertRaises(TypeError):
- ucl.dump(0, 0)
-
- def test_none(self):
- self.assertEqual(ucl.dump(None), None)
-
- def test_int(self):
- self.assertEqual(ucl.dump({ "a" : 1 }), "a = 1;\n")
-
- def test_nested_int(self):
- self.assertEqual(ucl.dump({ "a" : { "b" : 1 } }), "a {\n b = 1;\n}\n")
-
- def test_int_array(self):
- self.assertEqual(ucl.dump({ "a" : [1,2,3,4]}), "a [\n 1,\n 2,\n 3,\n 4,\n]\n")
-
- def test_str(self):
- self.assertEqual(ucl.dump({"a" : "b"}), "a = \"b\";\n")
-
- def test_float(self):
- self.assertEqual(ucl.dump({"a" : 1.1}), "a = 1.100000;\n")
-
- def test_boolean(self):
- totest = {"a" : True, "b" : False}
- correct = "a = true;\nb = false;\n"
- self.assertEqual(ucl.dump(totest), correct)
-
- def test_empty_ucl(self):
- self.assertEqual(ucl.dump({}), "")
-
- def test_json(self):
- self.assertEqual(ucl.dump({ "a" : 1, "b": "bleh;" }, ucl.UCL_EMIT_JSON), '{\n "a": 1,\n "b": "bleh;"\n}')
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/contrib/libucl/python/tests/__init__.py b/contrib/libucl/python/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libucl/python/tests/__init__.py
diff --git a/contrib/libucl/python/tests/compat.py b/contrib/libucl/python/tests/compat.py
new file mode 100644
index 0000000..5013826
--- /dev/null
+++ b/contrib/libucl/python/tests/compat.py
@@ -0,0 +1,8 @@
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+# Python 2.7 - 3.1
+if not hasattr(unittest.TestCase, 'assertRaisesRegex'):
+ unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
diff --git a/contrib/libucl/python/tests/test_dump.py b/contrib/libucl/python/tests/test_dump.py
new file mode 100644
index 0000000..3692414
--- /dev/null
+++ b/contrib/libucl/python/tests/test_dump.py
@@ -0,0 +1,66 @@
+from .compat import unittest
+import ucl
+import sys
+
+class DumpTest(unittest.TestCase):
+ def test_no_args(self):
+ with self.assertRaises(TypeError):
+ ucl.dump()
+
+ def test_none(self):
+ self.assertEqual(ucl.dump(None), None)
+
+ def test_null(self):
+ data = { "a" : None }
+ valid = "a = null;\n"
+ self.assertEqual(ucl.dump(data), valid)
+
+ def test_int(self):
+ data = { "a" : 1 }
+ valid = "a = 1;\n"
+ self.assertEqual(ucl.dump(data), valid)
+
+ def test_nested_int(self):
+ data = { "a" : { "b" : 1 } }
+ valid = "a {\n b = 1;\n}\n"
+ self.assertEqual(ucl.dump(data), valid)
+
+ def test_int_array(self):
+ data = { "a" : [1,2,3,4] }
+ valid = "a [\n 1,\n 2,\n 3,\n 4,\n]\n"
+ self.assertEqual(ucl.dump(data), valid)
+
+ def test_str(self):
+ data = { "a" : "b" }
+ valid = "a = \"b\";\n"
+ self.assertEqual(ucl.dump(data), valid)
+
+ @unittest.skipIf(sys.version_info[0] > 2, "Python3 uses unicode only")
+ def test_unicode(self):
+ data = { unicode("a") : unicode("b") }
+ valid = unicode("a = \"b\";\n")
+ self.assertEqual(ucl.dump(data), valid)
+
+ def test_float(self):
+ data = { "a" : 1.1 }
+ valid = "a = 1.100000;\n"
+ self.assertEqual(ucl.dump(data), valid)
+
+ def test_boolean(self):
+ data = { "a" : True, "b" : False }
+ valid = [
+ "a = true;\nb = false;\n",
+ "b = false;\na = true;\n"
+ ]
+ self.assertIn(ucl.dump(data), valid)
+
+ def test_empty_ucl(self):
+ self.assertEqual(ucl.dump({}), "")
+
+ def test_json(self):
+ data = { "a" : 1, "b": "bleh;" }
+ valid = [
+ '{\n "a": 1,\n "b": "bleh;"\n}',
+ '{\n "b": "bleh;",\n "a": 1\n}'
+ ]
+ self.assertIn(ucl.dump(data, ucl.UCL_EMIT_JSON), valid)
diff --git a/contrib/libucl/python/tests/test_load.py b/contrib/libucl/python/tests/test_load.py
new file mode 100644
index 0000000..786587a
--- /dev/null
+++ b/contrib/libucl/python/tests/test_load.py
@@ -0,0 +1,107 @@
+from .compat import unittest
+import ucl
+
+class LoadTest(unittest.TestCase):
+ def test_no_args(self):
+ with self.assertRaises(TypeError):
+ ucl.load()
+
+ def test_multi_args(self):
+ with self.assertRaises(TypeError):
+ ucl.load(0,0)
+
+ def test_none(self):
+ self.assertEqual(ucl.load(None), None)
+
+ def test_null(self):
+ data = "a: null"
+ valid = { "a" : None }
+ self.assertEqual(ucl.load(data), valid)
+
+ def test_int(self):
+ data = "a : 1"
+ valid = { "a" : 1 }
+ self.assertEqual(ucl.load(data), valid)
+
+ def test_braced_int(self):
+ data = "{a : 1}"
+ valid = { "a" : 1 }
+ self.assertEqual(ucl.load(data), valid)
+
+ def test_nested_int(self):
+ data = "a : { b : 1 }"
+ valid = { "a" : { "b" : 1 } }
+ self.assertEqual(ucl.load(data), valid)
+
+ def test_str(self):
+ data = "a : b"
+ valid = { "a" : "b" }
+ self.assertEqual(ucl.load(data), valid)
+
+ def test_float(self):
+ data = "a : 1.1"
+ valid = {"a" : 1.1}
+ self.assertEqual(ucl.load(data), valid)
+
+ def test_boolean(self):
+ data = (
+ "a : True;" \
+ "b : False"
+ )
+ valid = { "a" : True, "b" : False }
+ self.assertEqual(ucl.load(data), valid)
+
+ def test_empty_ucl(self):
+ self.assertEqual(ucl.load("{}"), {})
+
+ def test_single_brace(self):
+ self.assertEqual(ucl.load("{"), {})
+
+ def test_single_back_brace(self):
+ self.assertEqual(ucl.load("}"), {})
+
+ def test_single_square_forward(self):
+ self.assertEqual(ucl.load("["), [])
+
+ def test_invalid_ucl(self):
+ with self.assertRaisesRegex(ValueError, "unfinished key$"):
+ ucl.load('{ "var"')
+
+ def test_comment_ignored(self):
+ self.assertEqual(ucl.load("{/*1*/}"), {})
+
+ def test_1_in(self):
+ valid = { 'key1': 'value' }
+ with open("../tests/basic/1.in", "r") as in1:
+ self.assertEqual(ucl.load(in1.read()), valid)
+
+ def test_every_type(self):
+ data = ("""{
+ "key1": value;
+ "key2": value2;
+ "key3": "value;"
+ "key4": 1.0,
+ "key5": -0xdeadbeef
+ "key6": 0xdeadbeef.1
+ "key7": 0xreadbeef
+ "key8": -1e-10,
+ "key9": 1
+ "key10": true
+ "key11": no
+ "key12": yes
+ }""")
+ valid = {
+ 'key1': 'value',
+ 'key2': 'value2',
+ 'key3': 'value;',
+ 'key4': 1.0,
+ 'key5': -3735928559,
+ 'key6': '0xdeadbeef.1',
+ 'key7': '0xreadbeef',
+ 'key8': -1e-10,
+ 'key9': 1,
+ 'key10': True,
+ 'key11': False,
+ 'key12': True,
+ }
+ self.assertEqual(ucl.load(data), valid)
diff --git a/contrib/libucl/python/tests/test_validation.py b/contrib/libucl/python/tests/test_validation.py
new file mode 100644
index 0000000..f7c853a
--- /dev/null
+++ b/contrib/libucl/python/tests/test_validation.py
@@ -0,0 +1,50 @@
+from .compat import unittest
+import ucl
+import json
+import os.path
+import glob
+import re
+
+TESTS_SCHEMA_FOLDER = '../tests/schema/*.json'
+
+comment_re = re.compile('\/\*((?!\*\/).)*?\*\/', re.DOTALL | re.MULTILINE)
+def json_remove_comments(content):
+ return comment_re.sub('', content)
+
+class ValidationTest(unittest.TestCase):
+ def validate(self, jsonfile):
+ def perform_test(schema, data, valid, description):
+ msg = '%s (valid=%r)' % (description, valid)
+ if valid:
+ self.assertTrue(ucl.validate(schema, data), msg)
+ else:
+ with self.assertRaises(ucl.SchemaError):
+ ucl.validate(schema, data)
+ self.fail(msg) # fail() will be called only if SchemaError is not raised
+
+ with open(jsonfile) as f:
+ try:
+ # data = json.load(f)
+ data = json.loads(json_remove_comments(f.read()))
+ except ValueError as e:
+ raise self.skipTest('Failed to load JSON: %s' % str(e))
+
+ for testgroup in data:
+ for test in testgroup['tests']:
+ perform_test(testgroup['schema'], test['data'],
+ test['valid'], test['description'])
+
+ @classmethod
+ def setupValidationTests(cls):
+ """Creates each test dynamically from a folder"""
+ def test_gen(filename):
+ def run_test(self):
+ self.validate(filename)
+ return run_test
+
+ for jsonfile in glob.glob(TESTS_SCHEMA_FOLDER):
+ testname = os.path.splitext(os.path.basename(jsonfile))[0]
+ setattr(cls, 'test_%s' % testname, test_gen(jsonfile))
+
+
+ValidationTest.setupValidationTests()
diff --git a/contrib/libucl/src/ucl_parser.c b/contrib/libucl/src/ucl_parser.c
index fc7cea0..0f029ea 100644
--- a/contrib/libucl/src/ucl_parser.c
+++ b/contrib/libucl/src/ucl_parser.c
@@ -342,6 +342,7 @@ ucl_check_variable_safe (struct ucl_parser *parser, const char *ptr, size_t rema
/* Call generic handler */
if (parser->var_handler (ptr, remain, &dst, &dstlen, &need_free,
parser->var_data)) {
+ *out_len += dstlen;
*found = true;
if (need_free) {
free (dst);
@@ -458,11 +459,18 @@ ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
}
if (!found) {
if (strict && parser->var_handler != NULL) {
- if (parser->var_handler (ptr, remain, &dst, &dstlen, &need_free,
+ size_t var_len = 0;
+ while (var_len < remain && p[var_len] != '}')
+ var_len ++;
+
+ if (parser->var_handler (p, var_len, &dst, &dstlen, &need_free,
parser->var_data)) {
memcpy (d, dst, dstlen);
- ret += dstlen;
- d += remain;
+ ret += var_len;
+ d += dstlen;
+ if (need_free) {
+ free (dst);
+ }
found = true;
}
}
diff --git a/contrib/libucl/src/ucl_schema.c b/contrib/libucl/src/ucl_schema.c
index 4d7c871..c3aa8a7 100644
--- a/contrib/libucl/src/ucl_schema.c
+++ b/contrib/libucl/src/ucl_schema.c
@@ -69,7 +69,7 @@ ucl_schema_create_error (struct ucl_schema_error *err,
* Check whether we have a pattern specified
*/
static const ucl_object_t *
-ucl_schema_test_pattern (const ucl_object_t *obj, const char *pattern)
+ucl_schema_test_pattern (const ucl_object_t *obj, const char *pattern, bool recursive)
{
const ucl_object_t *res = NULL;
#ifdef HAVE_REGEX_H
@@ -78,11 +78,16 @@ ucl_schema_test_pattern (const ucl_object_t *obj, const char *pattern)
ucl_object_iter_t iter = NULL;
if (regcomp (&reg, pattern, REG_EXTENDED | REG_NOSUB) == 0) {
- while ((elt = ucl_object_iterate (obj, &iter, true)) != NULL) {
- if (regexec (&reg, ucl_object_key (elt), 0, NULL, 0) == 0) {
- res = elt;
- break;
+ if (recursive) {
+ while ((elt = ucl_object_iterate (obj, &iter, true)) != NULL) {
+ if (regexec (&reg, ucl_object_key (elt), 0, NULL, 0) == 0) {
+ res = elt;
+ break;
+ }
}
+ } else {
+ if (regexec (&reg, ucl_object_key (obj), 0, NULL, 0) == 0)
+ res = obj;
}
regfree (&reg);
}
@@ -205,12 +210,17 @@ ucl_schema_validate_object (const ucl_object_t *schema,
}
}
else if (strcmp (ucl_object_key (elt), "patternProperties") == 0) {
+ const ucl_object_t *vobj;
+ ucl_object_iter_t viter;
piter = NULL;
while (ret && (prop = ucl_object_iterate (elt, &piter, true)) != NULL) {
- found = ucl_schema_test_pattern (obj, ucl_object_key (prop));
- if (found) {
- ret = ucl_schema_validate (prop, found, true, err, root,
- ext_ref);
+ viter = NULL;
+ while (ret && (vobj = ucl_object_iterate (obj, &viter, true)) != NULL) {
+ found = ucl_schema_test_pattern (vobj, ucl_object_key (prop), false);
+ if (found) {
+ ret = ucl_schema_validate (prop, found, true, err, root,
+ ext_ref);
+ }
}
}
}
@@ -234,7 +244,7 @@ ucl_schema_validate_object (const ucl_object_t *schema,
piter = NULL;
pat = ucl_object_lookup (schema, "patternProperties");
while ((pelt = ucl_object_iterate (pat, &piter, true)) != NULL) {
- found = ucl_schema_test_pattern (obj, ucl_object_key (pelt));
+ found = ucl_schema_test_pattern (obj, ucl_object_key (pelt), true);
if (found != NULL) {
break;
}
diff --git a/contrib/libucl/src/ucl_util.c b/contrib/libucl/src/ucl_util.c
index 900658b..ccc4373 100644
--- a/contrib/libucl/src/ucl_util.c
+++ b/contrib/libucl/src/ucl_util.c
@@ -1795,8 +1795,9 @@ ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool n
}
bool
-ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
- unsigned priority)
+ucl_parser_add_file_full (struct ucl_parser *parser, const char *filename,
+ unsigned priority, enum ucl_duplicate_strategy strat,
+ enum ucl_parse_type parse_type)
{
unsigned char *buf;
size_t len;
@@ -1819,7 +1820,8 @@ ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
}
parser->cur_file = strdup (realbuf);
ucl_parser_set_filevars (parser, realbuf, false);
- ret = ucl_parser_add_chunk_priority (parser, buf, len, priority);
+ ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat,
+ parse_type);
if (len > 0) {
ucl_munmap (buf, len);
@@ -1829,14 +1831,27 @@ ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
}
bool
+ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
+ unsigned priority)
+{
+ if (parser == NULL) {
+ return false;
+ }
+
+ return ucl_parser_add_file_full(parser, filename, priority,
+ UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
+}
+
+bool
ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
{
if (parser == NULL) {
return false;
}
- return ucl_parser_add_file_priority(parser, filename,
- parser->default_priority);
+ return ucl_parser_add_file_full(parser, filename,
+ parser->default_priority, UCL_DUPLICATE_APPEND,
+ UCL_PARSE_UCL);
}
bool
diff --git a/contrib/libucl/tests/schema/patternProperties.json b/contrib/libucl/tests/schema/patternProperties.json
index 18586e5..e386b6b 100644
--- a/contrib/libucl/tests/schema/patternProperties.json
+++ b/contrib/libucl/tests/schema/patternProperties.json
@@ -24,6 +24,11 @@
"valid": false
},
{
+ "description": "a single invalid match is invalid",
+ "data": {"fooooo": 2, "foo": "bar"},
+ "valid": false
+ },
+ {
"description": "multiple invalid matches is invalid",
"data": {"foo": "bar", "foooooo" : "baz"},
"valid": false
diff --git a/contrib/libucl/tests/schema/refRemote.json b/contrib/libucl/tests/schema/refRemote.json
index 0ba9adb..067c666 100644
--- a/contrib/libucl/tests/schema/refRemote.json
+++ b/contrib/libucl/tests/schema/refRemote.json
@@ -48,7 +48,7 @@
"valid": false
}
]
- },
+ }
/*
{
"description": "change resolution scope",
diff --git a/contrib/mdocml/INSTALL b/contrib/mdocml/INSTALL
index 085fb3e..58bef6a 100644
--- a/contrib/mdocml/INSTALL
+++ b/contrib/mdocml/INSTALL
@@ -1,4 +1,4 @@
-$Id: INSTALL,v 1.13 2015/11/07 14:01:16 schwarze Exp $
+$Id: INSTALL,v 1.15 2016/07/14 11:09:06 schwarze Exp $
About mdocml, the portable mandoc distribution
----------------------------------------------
@@ -16,7 +16,7 @@ tech@ mailing list, too.
Enjoy using the mandoc toolset!
-Ingo Schwarze, Karlsruhe, March 2015
+Ingo Schwarze, Karlsruhe, July 2016
Installation
@@ -52,7 +52,7 @@ and go back to step 2.
4. Run "make -n install" and check whether everything will be
installed to the intended places. Otherwise, put some *DIR or *NM*
-variables into "configure.local" and go back to step 2.
+variables into "configure.local" and go back to step 2.
5. Run "sudo make install". If you intend to build a binary
package using some kind of fake root mechanism, you may need a
@@ -63,7 +63,7 @@ in the "Makefile" to understand how DESTDIR is used.
manpath(1), make sure it is configured correctly, in particular,
it returns all directory trees where manual pages are installed.
Otherwise, if your system uses man.conf(5), make sure it contains
-a "_whatdb" line for each directory tree, and the order of these
+a "manpath" line for each directory tree, and the order of these
lines meets your wishes.
7. If you compiled with database support, run the command "sudo
diff --git a/contrib/mdocml/LICENSE b/contrib/mdocml/LICENSE
index ad3cd4b..57e5656 100644
--- a/contrib/mdocml/LICENSE
+++ b/contrib/mdocml/LICENSE
@@ -1,11 +1,11 @@
-$Id: LICENSE,v 1.11 2015/11/07 17:58:55 schwarze Exp $
+$Id: LICENSE,v 1.12 2016/07/07 23:46:36 schwarze Exp $
With the exceptions noted below, all code and documentation
contained in the mdocml toolkit is protected by the Copyright
of the following developers:
Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
-Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
+Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
Copyright (c) 2009, 2010, 2011, 2012 Joerg Sonnenberger <joerg@netbsd.org>
Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
diff --git a/contrib/mdocml/Makefile b/contrib/mdocml/Makefile
index 9be2bd9..f76b137 100644
--- a/contrib/mdocml/Makefile
+++ b/contrib/mdocml/Makefile
@@ -1,7 +1,7 @@
-# $Id: Makefile,v 1.480 2015/11/07 21:53:14 schwarze Exp $
+# $Id: Makefile,v 1.488 2016/07/12 05:18:38 kristaps Exp $
#
# Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
-# Copyright (c) 2011, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+# Copyright (c) 2011, 2013-2016 Ingo Schwarze <schwarze@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -15,7 +15,7 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-VERSION = 1.13.3
+VERSION = 1.13.4
# === LIST OF FILES ====================================================
@@ -31,6 +31,9 @@ TESTSRCS = test-dirent-namlen.c \
test-pledge.c \
test-progname.c \
test-reallocarray.c \
+ test-rewb-bsd.c \
+ test-rewb-sysv.c \
+ test-sandbox_init.c \
test-sqlite3.c \
test-sqlite3_errstr.c \
test-strcasestr.c \
@@ -138,6 +141,7 @@ DISTFILES = INSTALL \
makewhatis.8 \
man.1 \
man.7 \
+ man.cgi.3 \
man.cgi.8 \
man.conf.5 \
man.h \
@@ -164,6 +168,7 @@ DISTFILES = INSTALL \
predefs.in \
roff.7 \
roff.h \
+ roff_int.h \
soelim.1 \
st.in \
tag.h \
@@ -293,6 +298,7 @@ WWW_MANS = apropos.1.html \
roff.7.html \
tbl.7.html \
makewhatis.8.html \
+ man.cgi.3.html \
man.cgi.8.html \
man.h.html \
manconf.h.html \
@@ -392,34 +398,30 @@ db-install: base-build
cgi-install: cgi-build
mkdir -p $(DESTDIR)$(CGIBINDIR)
mkdir -p $(DESTDIR)$(HTDOCDIR)
- mkdir -p $(DESTDIR)$(WWWPREFIX)/man/mandoc/man1
- mkdir -p $(DESTDIR)$(WWWPREFIX)/man/mandoc/man8
$(INSTALL_PROGRAM) man.cgi $(DESTDIR)$(CGIBINDIR)
$(INSTALL_DATA) mandoc.css $(DESTDIR)$(HTDOCDIR)
- $(INSTALL_MAN) apropos.1 $(DESTDIR)$(WWWPREFIX)/man/mandoc/man1/
- $(INSTALL_MAN) man.cgi.8 $(DESTDIR)$(WWWPREFIX)/man/mandoc/man8/
Makefile.local config.h: configure ${TESTSRCS}
@echo "$@ is out of date; please run ./configure"
@exit 1
libmandoc.a: $(COMPAT_OBJS) $(LIBMANDOC_OBJS)
- $(AR) rs $@ $(COMPAT_OBJS) $(LIBMANDOC_OBJS)
+ ar rs $@ $(COMPAT_OBJS) $(LIBMANDOC_OBJS)
mandoc: $(MAIN_OBJS) libmandoc.a
- $(CC) $(LDFLAGS) -o $@ $(MAIN_OBJS) libmandoc.a $(DBLIB)
+ $(CC) -o $@ $(LDFLAGS) $(MAIN_OBJS) libmandoc.a $(LDADD)
manpage: $(MANPAGE_OBJS) libmandoc.a
- $(CC) $(LDFLAGS) -o $@ $(MANPAGE_OBJS) libmandoc.a $(DBLIB)
+ $(CC) -o $@ $(LDFLAGS) $(MANPAGE_OBJS) libmandoc.a $(LDADD)
man.cgi: $(CGI_OBJS) libmandoc.a
- $(CC) $(LDFLAGS) $(STATIC) -o $@ $(CGI_OBJS) libmandoc.a $(DBLIB)
+ $(CC) $(STATIC) -o $@ $(LDFLAGS) $(CGI_OBJS) libmandoc.a $(LDADD)
demandoc: $(DEMANDOC_OBJS) libmandoc.a
- $(CC) $(LDFLAGS) -o $@ $(DEMANDOC_OBJS) libmandoc.a $(DBLIB)
+ $(CC) -o $@ $(LDFLAGS) $(DEMANDOC_OBJS) libmandoc.a $(LDADD)
soelim: $(SOELIM_OBJS)
- $(CC) $(LDFLAGS) -o $@ $(SOELIM_OBJS)
+ $(CC) -o $@ $(LDFLAGS) $(SOELIM_OBJS)
# --- maintainer targets ---
@@ -439,6 +441,8 @@ depend: config.h
Makefile.depend > Makefile.tmp
mv Makefile.tmp Makefile.depend
+dist: mdocml.sha256
+
mdocml.sha256: mdocml.tar.gz
sha256 mdocml.tar.gz > $@
diff --git a/contrib/mdocml/NEWS b/contrib/mdocml/NEWS
index 985f265..7f5625a 100644
--- a/contrib/mdocml/NEWS
+++ b/contrib/mdocml/NEWS
@@ -1,7 +1,140 @@
-$Id: NEWS,v 1.10 2015/11/05 16:58:20 schwarze Exp $
+$Id: NEWS,v 1.12 2016/07/14 11:09:06 schwarze Exp $
This file lists the most important changes in the mdocml.bsd.lv distribution.
+Changes in version 1.13.4, released on July 14, 2016
+
+ --- MAJOR NEW FEATURES ---
+ * man.conf(5): Design and implement a simpler configuration file format.
+ * man(1): Leverage less(1) -T and :t in a way resembling ctags(1)
+ to jump to the definitions of various terms inside manual pages.
+ * soelim(1): New implementation by Baptiste Daroussin.
+ * privilege limitation: Use OpenBSD pledge(2) or OS X sandbox_init(3)
+ when available.
+ * man.cgi(8): Support short URIs like http://man.openbsd.org/mdoc .
+ * mandoc.css: Use one unified stylesheet rather than three different ones.
+ --- MAJOR FUNCTIONALLY RELEVANT BUGFIXES ---
+ * mdoc(7): Fix multiple aspects of SYNOPSIS .Nm formatting.
+ * man(1): Fix process group handling, avoiding unclean shutdowns.
+ --- PORTABILITY IMPROVEMENTS ---
+ * Correctly use the ohash(3) compatibility implementation
+ even when building without SQLite support.
+ * Add compat glue for building on Solaris 9 and 10.
+ * Let ./configure select a supported RE syntax for word boundaries.
+ * Support LDFLAGS, to be used for example for hardening options.
+ * Avoid mixing putchar(3) and putwchar(3) on the same file descriptor,
+ it resulted in output corruption on some platforms.
+ * Avoid reusing va_lists, use va_copy(3) for better portability.
+ * Do not hardcode the path to the more(1) program.
+ --- MINOR NEW FEATURES ---
+ * roff(7): Implement \n(.$ (number of macro arguments).
+ * roff(7): Fully implement \z (do not advance cursor).
+ * roff(7): Implement the `r' conditional (register exists).
+ * roff(7): Implement \\$* (interpolate all arguments).
+ * roff(7): Parse and ignore \, and \/ (italic corrections).
+ * When there is no -m, no -M, no MANPATH and no /etc/man.conf,
+ fall back to /usr/share/man:/usr/X11R6/man:/usr/local/man.
+ * man(1): Give manuals in purely numerical sections priority over
+ manuals of the same name in sections with an alphabetical suffix.
+ * man.cgi(8): Support "header.html" and "footer.html".
+ * man.cgi(8): Set the "autofocus" attribute on the query text box.
+ * man.cgi(8): Simplify the search form, drop two useless buttons.
+ * man.cgi(8): Delete the pseudo-manpath "mandoc", assume that
+ apropos(1) and man.cgi(8) are installed in the default manpath.
+ --- RELIABILITY BUGFIXES ---
+ * mdoc(7): Avoid a use after free and an assertion failure when nodes
+ are deleted during validation.
+ * mdoc(7): Avoid a NULL pointer access when .Bd has no arguments.
+ * mdoc(7): Avoid a NULL pointer access triggered by mismatching end macros.
+ * mdoc(7): Avoid an assertion when .Fo has no argument.
+ * mdoc(7): Avoid an assertion when .Ta<tab> occurs in .Bl -column.
+ * mdoc(7): Avoid an assertion when a body gets broken and has a tail.
+ * roff(7): Avoid an assertion caused by blanks inside \o.
+ * roff(7): Make .so links to gziped manuals work without mandoc.db(5).
+ * tbl(7): Avoid a use after free when the last line of a layout is empty.
+ * eqn(7): Avoid an infinite loop caused by recursive "define".
+ * makewhatis(8): Avoid a segfault caused by unusual directory structures.
+ * Fix handling of leading, trailing, and double colons in MANPATH and -m.
+ --- MINOR BUGFIXES ---
+ * mdoc(7): Put arguments to end macros of broken partial explicit blocks
+ inside the breaking block.
+ * mdoc(7): Let .Dv force normal font.
+ * mdoc(7): Make trailing whitespace significant in .Bl -tag widths.
+ * mdoc(7): Fix macro interpretation around tabs in .Bl -column.
+ * man(7): Use the default width for .RS without arguments.
+ * man(7): On a new RS nesting level, the saved width starts from
+ the default width, not from the saved width of the previous level.
+ * man(7): Allow .PD in next-line scope.
+ * man(7): Improve handling of empty .HP.
+ * man(7): Improve formatting of .br and .sp inside .HP.
+ * man(7): Do not mistreat empty arguments to font alternating
+ macros as vertical spacing requests.
+ * man(7): Allow fill mode changes in tagged paragraph next-line scope.
+ * man(7): Fix minor bugs in block rewinding and simplify the related code.
+ * man(7): Add missing line breaks before subsection headers.
+ * man(7): Give section and subsection headers hanging indentation.
+ * man(7): Make trailing whitespace significant in .TP widths.
+ * roff(7): Don't allow breaking the output line after hyphens
+ that immediately follow escape sequences.
+ * roff(7): Ignore blank characters at the beginning of conditional blocks.
+ * roff(7): Escape breakable hyphens only after handling input line traps.
+ * roff(7): Reject \[uD800] to \[uDFFF] (surrogates) in the parser.
+ * tbl(7): Allow more than one data field after T} on the same input line.
+ * terminal output: Apply bold and italic to non-ASCII Unicode codepoints.
+ * terminal output: Improve rounding rules for horizontal scaling widths.
+ * HTML output: Render ASCII_NBRSP as "&nbsp;", not "-".
+ * man(1): Do not match the first part of a name if it continues with a dot.
+ * man(1): Keep working even if the current directory is unusable.
+ * man(1): Better error message when $PAGER is invalid.
+ * makewhatis(8): Improve handling of .Va and .Vt macros.
+ * apropos(1): Print "nothing appropriate" to stderr when appropriate.
+ * apropos(1): Abort with a useful error message when elementary
+ database operations like preparing queries or binding variables fail.
+ --- STRUCTURAL CHANGES, no functional change ---
+ * mdoc(7) and man(7): Unified data structures struct roff_node etc.
+ * mdoc(7) and man(7): Unified node handling library in roff.c.
+ * mdoc(7) and man(7): Seperate validation phase from parsing.
+ * roff(7): Major character table cleanup.
+ * Link with libz rather than forking gunzip(1).
+ --- THANKS TO ---
+ * Baptiste Daroussin (FreeBSD) for the new soelim(1)
+ and for release testing.
+ * Anthony Bentley (OpenBSD) for unifying mandoc.css, two nice
+ patches for man.cgi(8), some documentation patches, some bug
+ reports, and various useful discussions.
+ * Todd Miller (OpenBSD) for lots of help with process group and
+ signal handling, a few patches, some bug reports and some useful
+ discussions.
+ * Jonathan Gray (OpenBSD) for yet more testing with afl(1)
+ again resulting in more than half a dozen important bug reports.
+ * Svyatoslav Mishyn (Crux Linux) for some patches, several bug
+ reports, and extensive release testing.
+ * Christian Neukirchen (void Linux) for a number of compatibility
+ patches and suggestions and several bug reports.
+ * Christos Zoulas (NetBSD) for a bug fix patch and some useful
+ suggestions for cleanup.
+ * Florian Obser (OpenBSD) for a bugfix patch and some bug reports.
+ * Sevan Janiyan for help with Solaris compatibility and release
+ testing on many platforms.
+ * Jan Holzhueter and OpenCSW in general for help with Solaris
+ compatibility, and for providing me with a Solaris 9/10/11 testing
+ environment.
+ * Michael McConville (OpenBSD) for some simple cleanup patches.
+ * Thomas Klausner (NetBSD) for some bug reports and release testing.
+ * Christian Weisgerber, Dmitrij Czarkoff, Igor Sobrado,
+ Ken Westerback, Marc Espie, Mike Belopuhov, Rafael Neves,
+ Ted Unangst, Tim van der Molen, Theo Buehler, Theo de Raadt
+ (OpenBSD), Kurt Jaeger, Dag Erling Smoergrav (FreeBSD),
+ Joerg Sonnenberger (NetBSD), Carsten Kunze (Heirloom troff),
+ Daniel Levai, Fabian Raetz, Jan Stary, Jean-Yves Migeon,
+ Lorenzo Beretta, Markus Waldeck, Maxim Belooussov, Michael Reed,
+ Peter Bray, and Serguey Parkhomovsky for bug reports and feature
+ suggestions.
+ * Alexander Hall, Andrew Fresh, Antoine Jacoutot, Doug Hogan,
+ Jason McIntyre, Jasper Lievisse Adriaanse, Kent Spillner,
+ Nicholas Marriott, Peter Hessler, Sebastien Marie, Stefan Sperling,
+ and Theo de Raadt (OpenBSD) for helpful discussions and feedback.
+
Changes in version 1.13.3, released on March 13, 2015
--- MAJOR NEW FEATURES ---
diff --git a/contrib/mdocml/TODO b/contrib/mdocml/TODO
index d24c939..99a16a9 100644
--- a/contrib/mdocml/TODO
+++ b/contrib/mdocml/TODO
@@ -1,6 +1,6 @@
************************************************************************
* Official mandoc TODO.
-* $Id: TODO,v 1.216 2016/01/08 01:37:32 schwarze Exp $
+* $Id: TODO,v 1.218 2016/06/05 21:06:04 schwarze Exp $
************************************************************************
Many issues are annotated for difficulty as follows:
@@ -416,6 +416,11 @@ are mere guesses, and some may be wrong.
see also matthew@ Fri, 18 Jul 2014 19:25:12 -0700
loc * exist * algo ** size * imp ***
+- In -man -Thtml, .nf does not preserve indentation.
+ It should either convert blanks to &nbsp;
+ or use <pre> rather than <div> (like .Bd -literal does).
+ Reported by afresh1@ 12 Apr 2016 14:35:45 -0700
+
- .Bf at the beginning of a paragraph inserts a bogus 1ex horizontal
space, see for example random(3). Introduced in
http://mdocml.bsd.lv/cgi-bin/cvsweb/mdoc_html.c.diff?r1=1.91&r2=1.92
@@ -583,8 +588,6 @@ are mere guesses, and some may be wrong.
to tech@mdocml, naddy@ Wed, 28 Sep 2011 11:21:46 +0200
wait! kristaps@ Sun, 02 Oct 2011 17:12:52 +0200
-- for system errors, use errno/strerror/warn/err
-
************************************************************************
* documentation issues
************************************************************************
@@ -628,9 +631,6 @@ Several areas can be cleaned up to make mandoc even faster. These are
* structural issues
************************************************************************
-- Use libz directly instead of forking gunzip(1).
- Suggested by bapt at FreeBSD among others.
-
- We use the input line number at several places to distinguish
same-line from different-line input. That plainly doesn't work
with user-defined macros, leading to random breakage.
diff --git a/contrib/mdocml/cgi.c b/contrib/mdocml/cgi.c
index 0b01d06..f8497b5 100644
--- a/contrib/mdocml/cgi.c
+++ b/contrib/mdocml/cgi.c
@@ -1,7 +1,7 @@
-/* $Id: cgi.c,v 1.116 2016/01/04 12:36:26 schwarze Exp $ */
+/* $Id: cgi.c,v 1.135 2016/07/11 22:48:37 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@usta.de>
+ * Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@usta.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -21,6 +21,7 @@
#include <sys/time.h>
#include <ctype.h>
+#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@@ -55,15 +56,20 @@ struct req {
struct query q;
char **p; /* array of available manpaths */
size_t psz; /* number of available manpaths */
+ int isquery; /* QUERY_STRING used, not PATH_INFO */
+};
+
+enum focus {
+ FOCUS_NONE = 0,
+ FOCUS_QUERY
};
-static void catman(const struct req *, const char *);
-static void format(const struct req *, const char *);
static void html_print(const char *);
static void html_putchar(char);
static int http_decode(char *);
-static void http_parse(struct req *, const char *);
-static void pathgen(struct req *);
+static void parse_manpath_conf(struct req *);
+static void parse_path_info(struct req *req, const char *path);
+static void parse_query_string(struct req *, const char *);
static void pg_error_badrequest(const char *);
static void pg_error_internal(void);
static void pg_index(const struct req *);
@@ -74,16 +80,18 @@ static void pg_searchres(const struct req *,
static void pg_show(struct req *, const char *);
static void resp_begin_html(int, const char *);
static void resp_begin_http(int, const char *);
+static void resp_catman(const struct req *, const char *);
static void resp_copy(const char *);
static void resp_end_html(void);
-static void resp_searchform(const struct req *);
+static void resp_format(const struct req *, const char *);
+static void resp_searchform(const struct req *, enum focus);
static void resp_show(const struct req *, const char *);
static void set_query_attr(char **, char **);
static int validate_filename(const char *);
static int validate_manpath(const struct req *, const char *);
static int validate_urifrag(const char *);
-static const char *scriptname; /* CGI script name */
+static const char *scriptname = SCRIPT_NAME;
static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
static const char *const sec_numbers[] = {
@@ -106,16 +114,16 @@ static const int sec_MAX = sizeof(sec_names) / sizeof(char *);
static const char *const arch_names[] = {
"amd64", "alpha", "armish", "armv7",
- "aviion", "hppa", "hppa64", "i386",
- "ia64", "landisk", "loongson", "luna88k",
- "macppc", "mips64", "octeon", "sgi",
- "socppc", "solbourne", "sparc", "sparc64",
- "vax", "zaurus",
+ "hppa", "hppa64", "i386", "landisk",
+ "loongson", "luna88k", "macppc", "mips64",
+ "octeon", "sgi", "socppc", "sparc",
+ "sparc64", "zaurus",
"amiga", "arc", "arm32", "atari",
- "beagle", "cats", "hp300", "mac68k",
- "mvme68k", "mvme88k", "mvmeppc", "palm",
- "pc532", "pegasos", "pmax", "powerpc",
- "sun3", "wgrisc", "x68k"
+ "aviion", "beagle", "cats", "hp300",
+ "ia64", "mac68k", "mvme68k", "mvme88k",
+ "mvmeppc", "palm", "pc532", "pegasos",
+ "pmax", "powerpc", "solbourne", "sun3",
+ "vax", "wgrisc", "x68k"
};
static const int arch_MAX = sizeof(arch_names) / sizeof(char *);
@@ -182,11 +190,12 @@ set_query_attr(char **attr, char **val)
* and store the values into the query structure.
*/
static void
-http_parse(struct req *req, const char *qs)
+parse_query_string(struct req *req, const char *qs)
{
char *key, *val;
size_t keysz, valsz;
+ req->isquery = 1;
req->q.manpath = NULL;
req->q.arch = NULL;
req->q.sec = NULL;
@@ -338,14 +347,14 @@ resp_begin_html(int code, const char *msg)
resp_begin_http(code, msg);
printf("<!DOCTYPE html>\n"
- "<HTML>\n"
- "<HEAD>\n"
- "<META CHARSET=\"UTF-8\" />\n"
- "<LINK REL=\"stylesheet\" HREF=\"%s/mandoc.css\""
- " TYPE=\"text/css\" media=\"all\">\n"
- "<TITLE>%s</TITLE>\n"
- "</HEAD>\n"
- "<BODY>\n"
+ "<html>\n"
+ "<head>\n"
+ "<meta charset=\"UTF-8\"/>\n"
+ "<link rel=\"stylesheet\" href=\"%s/mandoc.css\""
+ " type=\"text/css\" media=\"all\">\n"
+ "<title>%s</title>\n"
+ "</head>\n"
+ "<body>\n"
"<!-- Begin page content. //-->\n",
CSS_DIR, CUSTOMIZE_TITLE);
@@ -358,103 +367,87 @@ resp_end_html(void)
resp_copy(MAN_DIR "/footer.html");
- puts("</BODY>\n"
- "</HTML>");
+ puts("</body>\n"
+ "</html>");
}
static void
-resp_searchform(const struct req *req)
+resp_searchform(const struct req *req, enum focus focus)
{
int i;
puts("<!-- Begin search form. //-->");
- printf("<DIV ID=\"mancgi\">\n"
- "<FORM ACTION=\"%s\" METHOD=\"get\">\n"
- "<FIELDSET>\n"
- "<LEGEND>Manual Page Search Parameters</LEGEND>\n",
+ printf("<div id=\"mancgi\">\n"
+ "<form action=\"/%s\" method=\"get\">\n"
+ "<fieldset>\n"
+ "<legend>Manual Page Search Parameters</legend>\n",
scriptname);
/* Write query input box. */
- printf( "<TABLE><TR><TD>\n"
- "<INPUT TYPE=\"text\" NAME=\"query\" VALUE=\"");
- if (NULL != req->q.query)
+ printf("<input type=\"text\" name=\"query\" value=\"");
+ if (req->q.query != NULL)
html_print(req->q.query);
- puts("\" SIZE=\"40\">");
-
- /* Write submission and reset buttons. */
-
- printf( "<INPUT TYPE=\"submit\" VALUE=\"Submit\">\n"
- "<INPUT TYPE=\"reset\" VALUE=\"Reset\">\n");
+ printf( "\" size=\"40\"");
+ if (focus == FOCUS_QUERY)
+ printf(" autofocus");
+ puts(">");
- /* Write show radio button */
+ /* Write submission buttons. */
- printf( "</TD><TD>\n"
- "<INPUT TYPE=\"radio\" ");
- if (req->q.equal)
- printf("CHECKED=\"checked\" ");
- printf( "NAME=\"apropos\" ID=\"show\" VALUE=\"0\">\n"
- "<LABEL FOR=\"show\">Show named manual page</LABEL>\n");
+ printf( "<button type=\"submit\" name=\"apropos\" value=\"0\">"
+ "man</button>\n"
+ "<button type=\"submit\" name=\"apropos\" value=\"1\">"
+ "apropos</button>\n<br/>\n");
/* Write section selector. */
- puts( "</TD></TR><TR><TD>\n"
- "<SELECT NAME=\"sec\">");
+ puts("<select name=\"sec\">");
for (i = 0; i < sec_MAX; i++) {
- printf("<OPTION VALUE=\"%s\"", sec_numbers[i]);
+ printf("<option value=\"%s\"", sec_numbers[i]);
if (NULL != req->q.sec &&
0 == strcmp(sec_numbers[i], req->q.sec))
- printf(" SELECTED=\"selected\"");
- printf(">%s</OPTION>\n", sec_names[i]);
+ printf(" selected=\"selected\"");
+ printf(">%s</option>\n", sec_names[i]);
}
- puts("</SELECT>");
+ puts("</select>");
/* Write architecture selector. */
- printf( "<SELECT NAME=\"arch\">\n"
- "<OPTION VALUE=\"default\"");
+ printf( "<select name=\"arch\">\n"
+ "<option value=\"default\"");
if (NULL == req->q.arch)
- printf(" SELECTED=\"selected\"");
- puts(">All Architectures</OPTION>");
+ printf(" selected=\"selected\"");
+ puts(">All Architectures</option>");
for (i = 0; i < arch_MAX; i++) {
- printf("<OPTION VALUE=\"%s\"", arch_names[i]);
+ printf("<option value=\"%s\"", arch_names[i]);
if (NULL != req->q.arch &&
0 == strcmp(arch_names[i], req->q.arch))
- printf(" SELECTED=\"selected\"");
- printf(">%s</OPTION>\n", arch_names[i]);
+ printf(" selected=\"selected\"");
+ printf(">%s</option>\n", arch_names[i]);
}
- puts("</SELECT>");
+ puts("</select>");
/* Write manpath selector. */
if (req->psz > 1) {
- puts("<SELECT NAME=\"manpath\">");
+ puts("<select name=\"manpath\">");
for (i = 0; i < (int)req->psz; i++) {
- printf("<OPTION ");
+ printf("<option ");
if (strcmp(req->q.manpath, req->p[i]) == 0)
- printf("SELECTED=\"selected\" ");
- printf("VALUE=\"");
+ printf("selected=\"selected\" ");
+ printf("value=\"");
html_print(req->p[i]);
printf("\">");
html_print(req->p[i]);
- puts("</OPTION>");
+ puts("</option>");
}
- puts("</SELECT>");
+ puts("</select>");
}
- /* Write search radio button */
-
- printf( "</TD><TD>\n"
- "<INPUT TYPE=\"radio\" ");
- if (0 == req->q.equal)
- printf("CHECKED=\"checked\" ");
- printf( "NAME=\"apropos\" ID=\"search\" VALUE=\"1\">\n"
- "<LABEL FOR=\"search\">Search with apropos query</LABEL>\n");
-
- puts("</TD></TR></TABLE>\n"
- "</FIELDSET>\n"
- "</FORM>\n"
- "</DIV>");
+ puts("</fieldset>\n"
+ "</form>\n"
+ "</div>");
puts("<!-- End search form. //-->");
}
@@ -477,9 +470,6 @@ validate_manpath(const struct req *req, const char* manpath)
{
size_t i;
- if ( ! strcmp(manpath, "mandoc"))
- return 1;
-
for (i = 0; i < req->psz; i++)
if ( ! strcmp(manpath, req->p[i]))
return 1;
@@ -503,15 +493,16 @@ pg_index(const struct req *req)
{
resp_begin_html(200, NULL);
- resp_searchform(req);
- printf("<P>\n"
+ resp_searchform(req, FOCUS_QUERY);
+ printf("<p>\n"
"This web interface is documented in the\n"
- "<A HREF=\"%s/mandoc/man8/man.cgi.8\">man.cgi</A>\n"
+ "<a href=\"/%s%sman.cgi.8\">man.cgi(8)</a>\n"
"manual, and the\n"
- "<A HREF=\"%s/mandoc/man1/apropos.1\">apropos</A>\n"
+ "<a href=\"/%s%sapropos.1\">apropos(1)</a>\n"
"manual explains the query syntax.\n"
- "</P>\n",
- scriptname, scriptname);
+ "</p>\n",
+ scriptname, *scriptname == '\0' ? "" : "/",
+ scriptname, *scriptname == '\0' ? "" : "/");
resp_end_html();
}
@@ -519,10 +510,10 @@ static void
pg_noresult(const struct req *req, const char *msg)
{
resp_begin_html(200, NULL);
- resp_searchform(req);
- puts("<P>");
+ resp_searchform(req, FOCUS_QUERY);
+ puts("<p>");
puts(msg);
- puts("</P>");
+ puts("</p>");
resp_end_html();
}
@@ -531,12 +522,12 @@ pg_error_badrequest(const char *msg)
{
resp_begin_html(400, "Bad Request");
- puts("<H1>Bad Request</H1>\n"
- "<P>\n");
+ puts("<h1>Bad Request</h1>\n"
+ "<p>\n");
puts(msg);
printf("Try again from the\n"
- "<A HREF=\"%s\">main page</A>.\n"
- "</P>", scriptname);
+ "<a href=\"/%s\">main page</a>.\n"
+ "</p>", scriptname);
resp_end_html();
}
@@ -544,7 +535,7 @@ static void
pg_error_internal(void)
{
resp_begin_html(500, "Internal Server Error");
- puts("<P>Internal Server Error</P>");
+ puts("<p>Internal Server Error</p>");
resp_end_html();
}
@@ -552,28 +543,30 @@ static void
pg_searchres(const struct req *req, struct manpage *r, size_t sz)
{
char *arch, *archend;
- size_t i, iuse, isec;
+ const char *sec;
+ size_t i, iuse;
int archprio, archpriouse;
int prio, priouse;
- char sec;
for (i = 0; i < sz; i++) {
if (validate_filename(r[i].file))
continue;
- fprintf(stderr, "invalid filename %s in %s database\n",
+ warnx("invalid filename %s in %s database",
r[i].file, req->q.manpath);
pg_error_internal();
return;
}
- if (1 == sz) {
+ if (req->isquery && sz == 1) {
/*
* If we have just one result, then jump there now
* without any delay.
*/
printf("Status: 303 See Other\r\n");
- printf("Location: http://%s%s/%s/%s",
- HTTP_HOST, scriptname, req->q.manpath, r[0].file);
+ printf("Location: http://%s/%s%s%s/%s",
+ HTTP_HOST, scriptname,
+ *scriptname == '\0' ? "" : "/",
+ req->q.manpath, r[0].file);
printf("\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"\r\n");
@@ -581,50 +574,57 @@ pg_searchres(const struct req *req, struct manpage *r, size_t sz)
}
resp_begin_html(200, NULL);
- resp_searchform(req);
- puts("<DIV CLASS=\"results\">");
- puts("<TABLE>");
+ resp_searchform(req,
+ req->q.equal || sz == 1 ? FOCUS_NONE : FOCUS_QUERY);
- for (i = 0; i < sz; i++) {
- printf("<TR>\n"
- "<TD CLASS=\"title\">\n"
- "<A HREF=\"%s/%s/%s",
- scriptname, req->q.manpath, r[i].file);
- printf("\">");
- html_print(r[i].names);
- printf("</A>\n"
- "</TD>\n"
- "<TD CLASS=\"desc\">");
- html_print(r[i].output);
- puts("</TD>\n"
- "</TR>");
- }
+ if (sz > 1) {
+ puts("<div class=\"results\">");
+ puts("<table>");
- puts("</TABLE>\n"
- "</DIV>");
+ for (i = 0; i < sz; i++) {
+ printf("<tr>\n"
+ "<td class=\"title\">\n"
+ "<a href=\"/%s%s%s/%s",
+ scriptname, *scriptname == '\0' ? "" : "/",
+ req->q.manpath, r[i].file);
+ printf("\">");
+ html_print(r[i].names);
+ printf("</a>\n"
+ "</td>\n"
+ "<td class=\"desc\">");
+ html_print(r[i].output);
+ puts("</td>\n"
+ "</tr>");
+ }
+
+ puts("</table>\n"
+ "</div>");
+ }
/*
* In man(1) mode, show one of the pages
* even if more than one is found.
*/
- if (req->q.equal) {
- puts("<HR>");
+ if (req->q.equal || sz == 1) {
+ puts("<hr>");
iuse = 0;
- priouse = 10;
+ priouse = 20;
archpriouse = 3;
for (i = 0; i < sz; i++) {
- isec = strcspn(r[i].file, "123456789");
- sec = r[i].file[isec];
- if ('\0' == sec)
+ sec = r[i].file;
+ sec += strcspn(sec, "123456789");
+ if (sec[0] == '\0')
continue;
- prio = sec_prios[sec - '1'];
- if (NULL == req->q.arch) {
+ prio = sec_prios[sec[0] - '1'];
+ if (sec[1] != '/')
+ prio += 10;
+ if (req->q.arch == NULL) {
archprio =
- (NULL == (arch = strchr(
- r[i].file + isec, '/'))) ? 3 :
- (NULL == (archend = strchr(
- arch + 1, '/'))) ? 0 :
+ ((arch = strchr(sec + 1, '/'))
+ == NULL) ? 3 :
+ ((archend = strchr(arch + 1, '/'))
+ == NULL) ? 0 :
strncmp(arch, "amd64/",
archend - arch) ? 2 : 1;
if (archprio < archpriouse) {
@@ -648,7 +648,7 @@ pg_searchres(const struct req *req, struct manpage *r, size_t sz)
}
static void
-catman(const struct req *req, const char *file)
+resp_catman(const struct req *req, const char *file)
{
FILE *f;
char *p;
@@ -658,12 +658,12 @@ catman(const struct req *req, const char *file)
int italic, bold;
if ((f = fopen(file, "r")) == NULL) {
- puts("<P>You specified an invalid manual file.</P>");
+ puts("<p>You specified an invalid manual file.</p>");
return;
}
- puts("<DIV CLASS=\"catman\">\n"
- "<PRE>");
+ puts("<div class=\"catman\">\n"
+ "<pre>");
p = NULL;
sz = 0;
@@ -689,9 +689,9 @@ catman(const struct req *req, const char *file)
if ('\b' != p[i + 1]) {
if (italic)
- printf("</I>");
+ printf("</i>");
if (bold)
- printf("</B>");
+ printf("</b>");
italic = bold = 0;
html_putchar(p[i]);
continue;
@@ -702,9 +702,9 @@ catman(const struct req *req, const char *file)
if ('_' == p[i]) {
if (bold)
- printf("</B>");
+ printf("</b>");
if ( ! italic)
- printf("<I>");
+ printf("<i>");
bold = 0;
italic = 1;
i += 2;
@@ -726,9 +726,9 @@ catman(const struct req *req, const char *file)
('*' == p[i] && '|' == p[i + 2]) ||
('|' == p[i] && '*' == p[i + 2])) {
if (italic)
- printf("</I>");
+ printf("</i>");
if (bold)
- printf("</B>");
+ printf("</b>");
italic = bold = 0;
putchar('*');
i += 2;
@@ -740,9 +740,9 @@ catman(const struct req *req, const char *file)
('+' == p[i] && '|' == p[i + 1]) ||
('|' == p[i] && '+' == p[i + 1])) {
if (italic)
- printf("</I>");
+ printf("</i>");
if (bold)
- printf("</B>");
+ printf("</b>");
italic = bold = 0;
putchar('+');
i += 2;
@@ -752,9 +752,9 @@ catman(const struct req *req, const char *file)
/* Bold mode. */
if (italic)
- printf("</I>");
+ printf("</i>");
if ( ! bold)
- printf("<B>");
+ printf("<b>");
bold = 1;
italic = 0;
i += 2;
@@ -767,9 +767,9 @@ catman(const struct req *req, const char *file)
*/
if (italic)
- printf("</I>");
+ printf("</i>");
if (bold)
- printf("</B>");
+ printf("</b>");
if (i == len - 1 && p[i] != '\n')
html_putchar(p[i]);
@@ -778,14 +778,14 @@ catman(const struct req *req, const char *file)
}
free(p);
- puts("</PRE>\n"
- "</DIV>");
+ puts("</pre>\n"
+ "</div>");
fclose(f);
}
static void
-format(const struct req *req, const char *file)
+resp_format(const struct req *req, const char *file)
{
struct manoutput conf;
struct mparse *mp;
@@ -795,7 +795,7 @@ format(const struct req *req, const char *file)
int usepath;
if (-1 == (fd = open(file, O_RDONLY, 0))) {
- puts("<P>You specified an invalid manual file.</P>");
+ puts("<p>You specified an invalid manual file.</p>");
return;
}
@@ -807,17 +807,12 @@ format(const struct req *req, const char *file)
memset(&conf, 0, sizeof(conf));
conf.fragment = 1;
usepath = strcmp(req->q.manpath, req->p[0]);
- mandoc_asprintf(&conf.man, "%s?query=%%N&sec=%%S%s%s%s%s",
- scriptname,
- req->q.arch ? "&arch=" : "",
- req->q.arch ? req->q.arch : "",
- usepath ? "&manpath=" : "",
- usepath ? req->q.manpath : "");
+ mandoc_asprintf(&conf.man, "/%s%s%%N.%%S",
+ usepath ? req->q.manpath : "", usepath ? "/" : "");
mparse_result(mp, &man, NULL);
if (man == NULL) {
- fprintf(stderr, "fatal mandoc error: %s/%s\n",
- req->q.manpath, file);
+ warnx("fatal mandoc error: %s/%s", req->q.manpath, file);
pg_error_internal();
mparse_free(mp);
mchars_free();
@@ -848,9 +843,9 @@ resp_show(const struct req *req, const char *file)
file += 2;
if ('c' == *file)
- catman(req, file);
+ resp_catman(req, file);
else
- format(req, file);
+ resp_format(req, file);
}
static void
@@ -881,18 +876,12 @@ pg_show(struct req *req, const char *fullpath)
*/
if (chdir(manpath) == -1) {
- fprintf(stderr, "chdir %s: %s\n",
- manpath, strerror(errno));
+ warn("chdir %s", manpath);
pg_error_internal();
free(manpath);
return;
}
-
- if (strcmp(manpath, "mandoc")) {
- free(req->q.manpath);
- req->q.manpath = manpath;
- } else
- free(manpath);
+ free(manpath);
if ( ! validate_filename(file)) {
pg_error_badrequest(
@@ -901,7 +890,7 @@ pg_show(struct req *req, const char *fullpath)
}
resp_begin_html(200, NULL);
- resp_searchform(req);
+ resp_searchform(req, FOCUS_NONE);
resp_show(req, file);
resp_end_html();
}
@@ -923,9 +912,8 @@ pg_search(const struct req *req)
* relative to the manpath root.
*/
- if (-1 == (chdir(req->q.manpath))) {
- fprintf(stderr, "chdir %s: %s\n",
- req->q.manpath, strerror(errno));
+ if (chdir(req->q.manpath) == -1) {
+ warn("chdir %s", req->q.manpath);
pg_error_internal();
return;
}
@@ -1000,19 +988,7 @@ main(void)
itimer.it_interval.tv_sec = 2;
itimer.it_interval.tv_usec = 0;
if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) {
- fprintf(stderr, "setitimer: %s\n", strerror(errno));
- pg_error_internal();
- return EXIT_FAILURE;
- }
-
- /* Scan our run-time environment. */
-
- if (NULL == (scriptname = getenv("SCRIPT_NAME")))
- scriptname = "";
-
- if ( ! validate_urifrag(scriptname)) {
- fprintf(stderr, "unsafe SCRIPT_NAME \"%s\"\n",
- scriptname);
+ warn("setitimer");
pg_error_internal();
return EXIT_FAILURE;
}
@@ -1023,20 +999,31 @@ main(void)
* relative to the same position.
*/
- if (-1 == chdir(MAN_DIR)) {
- fprintf(stderr, "MAN_DIR: %s: %s\n",
- MAN_DIR, strerror(errno));
+ if (chdir(MAN_DIR) == -1) {
+ warn("MAN_DIR: %s", MAN_DIR);
pg_error_internal();
return EXIT_FAILURE;
}
memset(&req, 0, sizeof(struct req));
- pathgen(&req);
+ req.q.equal = 1;
+ parse_manpath_conf(&req);
- /* Next parse out the query string. */
+ /* Parse the path info and the query string. */
- if (NULL != (querystring = getenv("QUERY_STRING")))
- http_parse(&req, querystring);
+ if ((path = getenv("PATH_INFO")) == NULL)
+ path = "";
+ else if (*path == '/')
+ path++;
+
+ if (*path != '\0') {
+ parse_path_info(&req, path);
+ if (req.q.manpath == NULL || access(path, F_OK) == -1)
+ path = "";
+ } else if ((querystring = getenv("QUERY_STRING")) != NULL)
+ parse_query_string(&req, querystring);
+
+ /* Validate parsed data and add defaults. */
if (req.q.manpath == NULL)
req.q.manpath = mandoc_strdup(req.p[0]);
@@ -1054,12 +1041,6 @@ main(void)
/* Dispatch to the three different pages. */
- path = getenv("PATH_INFO");
- if (NULL == path)
- path = "";
- else if ('/' == *path)
- path++;
-
if ('\0' != *path)
pg_show(&req, path);
else if (NULL != req.q.query)
@@ -1078,19 +1059,95 @@ main(void)
}
/*
+ * If PATH_INFO is not a file name, translate it to a query.
+ */
+static void
+parse_path_info(struct req *req, const char *path)
+{
+ char *dir[4];
+ int i;
+
+ req->isquery = 0;
+ req->q.equal = 1;
+ req->q.manpath = mandoc_strdup(path);
+ req->q.arch = NULL;
+
+ /* Mandatory manual page name. */
+ if ((req->q.query = strrchr(req->q.manpath, '/')) == NULL) {
+ req->q.query = req->q.manpath;
+ req->q.manpath = NULL;
+ } else
+ *req->q.query++ = '\0';
+
+ /* Optional trailing section. */
+ if ((req->q.sec = strrchr(req->q.query, '.')) != NULL) {
+ if(isdigit((unsigned char)req->q.sec[1])) {
+ *req->q.sec++ = '\0';
+ req->q.sec = mandoc_strdup(req->q.sec);
+ } else
+ req->q.sec = NULL;
+ }
+
+ /* Handle the case of name[.section] only. */
+ if (req->q.manpath == NULL)
+ return;
+ req->q.query = mandoc_strdup(req->q.query);
+
+ /* Split directory components. */
+ dir[i = 0] = req->q.manpath;
+ while ((dir[i + 1] = strchr(dir[i], '/')) != NULL) {
+ if (++i == 3) {
+ pg_error_badrequest(
+ "You specified too many directory components.");
+ exit(EXIT_FAILURE);
+ }
+ *dir[i]++ = '\0';
+ }
+
+ /* Optional manpath. */
+ if ((i = validate_manpath(req, req->q.manpath)) == 0)
+ req->q.manpath = NULL;
+ else if (dir[1] == NULL)
+ return;
+
+ /* Optional section. */
+ if (strncmp(dir[i], "man", 3) == 0) {
+ free(req->q.sec);
+ req->q.sec = mandoc_strdup(dir[i++] + 3);
+ }
+ if (dir[i] == NULL) {
+ if (req->q.manpath == NULL)
+ free(dir[0]);
+ return;
+ }
+ if (dir[i + 1] != NULL) {
+ pg_error_badrequest(
+ "You specified an invalid directory component.");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Optional architecture. */
+ if (i) {
+ req->q.arch = mandoc_strdup(dir[i]);
+ if (req->q.manpath == NULL)
+ free(dir[0]);
+ } else
+ req->q.arch = dir[0];
+}
+
+/*
* Scan for indexable paths.
*/
static void
-pathgen(struct req *req)
+parse_manpath_conf(struct req *req)
{
FILE *fp;
char *dp;
size_t dpsz;
ssize_t len;
- if (NULL == (fp = fopen("manpath.conf", "r"))) {
- fprintf(stderr, "%s/manpath.conf: %s\n",
- MAN_DIR, strerror(errno));
+ if ((fp = fopen("manpath.conf", "r")) == NULL) {
+ warn("%s/manpath.conf", MAN_DIR);
pg_error_internal();
exit(EXIT_FAILURE);
}
@@ -1104,14 +1161,14 @@ pathgen(struct req *req)
req->p = mandoc_realloc(req->p,
(req->psz + 1) * sizeof(char *));
if ( ! validate_urifrag(dp)) {
- fprintf(stderr, "%s/manpath.conf contains "
- "unsafe path \"%s\"\n", MAN_DIR, dp);
+ warnx("%s/manpath.conf contains "
+ "unsafe path \"%s\"", MAN_DIR, dp);
pg_error_internal();
exit(EXIT_FAILURE);
}
- if (NULL != strchr(dp, '/')) {
- fprintf(stderr, "%s/manpath.conf contains "
- "path with slash \"%s\"\n", MAN_DIR, dp);
+ if (strchr(dp, '/') != NULL) {
+ warnx("%s/manpath.conf contains "
+ "path with slash \"%s\"", MAN_DIR, dp);
pg_error_internal();
exit(EXIT_FAILURE);
}
@@ -1121,8 +1178,8 @@ pathgen(struct req *req)
}
free(dp);
- if ( req->p == NULL ) {
- fprintf(stderr, "%s/manpath.conf is empty\n", MAN_DIR);
+ if (req->p == NULL) {
+ warnx("%s/manpath.conf is empty", MAN_DIR);
pg_error_internal();
exit(EXIT_FAILURE);
}
diff --git a/contrib/mdocml/cgi.h.example b/contrib/mdocml/cgi.h.example
index c4878d3..7e5f391 100644
--- a/contrib/mdocml/cgi.h.example
+++ b/contrib/mdocml/cgi.h.example
@@ -1,7 +1,8 @@
/* Example compile-time configuration file for man.cgi(8). */
#define HTTP_HOST "mdocml.bsd.lv"
-#define MAN_DIR "/var/www/man"
+#define SCRIPT_NAME "cgi-bin/man.cgi"
+#define MAN_DIR "/man"
#define CSS_DIR ""
#define CUSTOMIZE_TITLE "Manual pages with mandoc"
#define COMPAT_OLDURI Yes
diff --git a/contrib/mdocml/configure b/contrib/mdocml/configure
index 21997fc..6f2c411 100755
--- a/contrib/mdocml/configure
+++ b/contrib/mdocml/configure
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+# Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -36,7 +36,10 @@ OSNAME=
CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | make -f -`
CFLAGS="-g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings"
-DBLIB=
+LDADD=
+LDFLAGS=
+LD_OHASH=
+LD_SQLITE3=
STATIC="-static"
BUILD_DB=1
@@ -55,6 +58,7 @@ HAVE_PROGNAME=
HAVE_REALLOCARRAY=
HAVE_REWB_BSD=
HAVE_REWB_SYSV=
+HAVE_SANDBOX_INIT=
HAVE_STRCASESTR=
HAVE_STRINGLIST=
HAVE_STRLCAT=
@@ -183,6 +187,7 @@ runtest isblank ISBLANK || true
runtest mkdtemp MKDTEMP || true
runtest mmap MMAP || true
runtest pledge PLEDGE || true
+runtest sandbox_init SANDBOX_INIT || true
runtest progname PROGNAME || true
runtest reallocarray REALLOCARRAY || true
runtest rewb-bsd REWB_BSD || true
@@ -198,28 +203,32 @@ runtest vasprintf VASPRINTF || true
runtest wchar WCHAR || true
# --- sqlite3 ---
-DETECTLIB=
if [ ${BUILD_DB} -eq 0 ]; then
echo "BUILD_DB=0 (manual)" 1>&2
echo "BUILD_DB=0 (manual)" 1>&3
echo 1>&3
HAVE_SQLITE3=0
elif ismanual sqlite3 "${HAVE_SQLITE3}"; then
- DETECTLIB="-lsqlite3"
-elif [ -n "${DBLIB}" ]; then
- runtest sqlite3 SQLITE3 "${DBLIB}" || true
+ if [ -z "${LD_SQLITE3}" ]; then
+ LD_SQLITE3="-lsqlite3"
+ fi
+elif [ -n "${LD_SQLITE3}" ]; then
+ runtest sqlite3 SQLITE3 "${LD_SQLITE3}" || true
elif singletest sqlite3 SQLITE3 "-lsqlite3"; then
- DETECTLIB="-lsqlite3"
+ LD_SQLITE3="-lsqlite3"
elif runtest sqlite3 SQLITE3 \
"-I/usr/local/include -L/usr/local/lib -lsqlite3"; then
- DETECTLIB="-L/usr/local/lib -lsqlite3"
+ LD_SQLITE3="-L/usr/local/lib -lsqlite3"
CFLAGS="${CFLAGS} -I/usr/local/include"
fi
-if [ ${BUILD_DB} -gt 0 -a ${HAVE_SQLITE3} -eq 0 ]; then
- echo "BUILD_DB=0 (no sqlite3)" 1>&2
- echo "BUILD_DB=0 (no sqlite3)" 1>&3
- echo 1>&3
- BUILD_DB=0
+if [ ${HAVE_SQLITE3} -eq 0 ]; then
+ LD_SQLITE3=
+ if [ ${BUILD_DB} -gt 0 ]; then
+ echo "BUILD_DB=0 (no sqlite3)" 1>&2
+ echo "BUILD_DB=0 (no sqlite3)" 1>&3
+ echo 1>&3
+ BUILD_DB=0
+ fi
fi
# --- sqlite3_errstr ---
@@ -227,35 +236,30 @@ if [ ${BUILD_DB} -eq 0 ]; then
HAVE_SQLITE3_ERRSTR=1
elif ismanual sqlite3_errstr "${HAVE_SQLITE3_ERRSTR}"; then
:
-elif [ -n "${DBLIB}" ]; then
- runtest sqlite3_errstr SQLITE3_ERRSTR "${DBLIB}" || true
else
- runtest sqlite3_errstr SQLITE3_ERRSTR "${DETECTLIB}" || true
+ runtest sqlite3_errstr SQLITE3_ERRSTR "${LD_SQLITE3}" || true
fi
# --- ohash ---
-if [ ${BUILD_DB} -eq 0 ]; then
- HAVE_OHASH=1
-elif ismanual ohash "${HAVE_OHASH}"; then
+if ismanual ohash "${HAVE_OHASH}"; then
:
-elif [ -n "${DBLIB}" ]; then
- runtest ohash OHASH "${DBLIB}" || true
+elif [ -n "${LD_OHASH}" ]; then
+ runtest ohash OHASH "${LD_OHASH}" || true
elif singletest ohash OHASH; then
:
elif runtest ohash OHASH "-lutil"; then
- DETECTLIB="${DETECTLIB} -lutil"
+ LD_OHASH="-lutil"
fi
-
-# --- DBLIB ---
-if [ ${BUILD_DB} -eq 0 ]; then
- DBLIB="-lz"
-elif [ -z "${DBLIB}" ]; then
- DBLIB="${DETECTLIB} -lz"
- echo "DBLIB=\"${DBLIB}\"" 1>&2
- echo "DBLIB=\"${DBLIB}\"" 1>&3
- echo 1>&3
+if [ "${HAVE_OHASH}" -eq 0 ]; then
+ LD_OHASH=
fi
+# --- LDADD ---
+LDADD="${LDADD} ${LD_SQLITE3} ${LD_OHASH} -lz"
+echo "LDADD=\"${LDADD}\"" 1>&2
+echo "LDADD=\"${LDADD}\"" 1>&3
+echo 1>&3
+
# --- manpath ---
if ismanual manpath "${HAVE_MANPATH}"; then
:
@@ -315,6 +319,7 @@ cat << __HEREDOC__
#define HAVE_REALLOCARRAY ${HAVE_REALLOCARRAY}
#define HAVE_REWB_BSD ${HAVE_REWB_BSD}
#define HAVE_REWB_SYSV ${HAVE_REWB_SYSV}
+#define HAVE_SANDBOX_INIT ${HAVE_SANDBOX_INIT}
#define HAVE_STRCASESTR ${HAVE_STRCASESTR}
#define HAVE_STRINGLIST ${HAVE_STRINGLIST}
#define HAVE_STRLCAT ${HAVE_STRLCAT}
@@ -426,7 +431,8 @@ BUILD_TARGETS = ${BUILD_TARGETS}
INSTALL_TARGETS = ${INSTALL_TARGETS}
CC = ${CC}
CFLAGS = ${CFLAGS}
-DBLIB = ${DBLIB}
+LDADD = ${LDADD}
+LDFLAGS = ${LDFLAGS}
STATIC = ${STATIC}
PREFIX = ${PREFIX}
BINDIR = ${BINDIR}
diff --git a/contrib/mdocml/configure.local.example b/contrib/mdocml/configure.local.example
index de9f08f..c955a80 100644
--- a/contrib/mdocml/configure.local.example
+++ b/contrib/mdocml/configure.local.example
@@ -1,6 +1,6 @@
-# $Id: configure.local.example,v 1.10 2015/11/07 13:14:21 schwarze Exp $
+# $Id: configure.local.example,v 1.13 2016/07/14 11:09:06 schwarze Exp $
#
-# Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+# Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -65,7 +65,7 @@ MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man"
# If you do not want uname(3) to be called but instead want a fixed
# string to be used, use the following line:
-OSNAME="OpenBSD 5.6"
+OSNAME="OpenBSD 5.9"
# The following installation directories are used.
# It is possible to set only one or a few of these variables,
@@ -123,6 +123,26 @@ MANM_TBL="mandoc_tbl" # default is "tbl"
BINM_MAN=mman # default is "man"
BINM_SOELIM=msoelim # default is "soelim"
+# Before falling back to the bundled version of the ohash(3) hashing
+# library, autoconfiguration tries the following linker flag to
+# link against your system version. If you do have ohash(3) on
+# your system but it needs different linker flags, set the following
+# variable to specify the required linker flags.
+
+LD_OHASH="-lutil"
+
+# Some platforms may need additional linker flags to link against libmandoc
+# that are not autodetected.
+# For example, Solaris 9 and 10 need -lrt for nanosleep(2).
+
+LDADD="-lrt"
+
+# Some systems may want to set additional linker flags for all the
+# binaries, not only for those using libmandoc, for example for
+# hardening options.
+
+LDFLAGS="-Wl,-z,relro"
+
# It is possible to change the utility program used for installation
# and the modes files are installed with. The defaults are:
@@ -141,18 +161,16 @@ INSTALL_DATA="${INSTALL} -m 0444"
BUILD_DB=0
-# Two libraries are needed: SQLite3 and ohash(3).
-# Autoconfiguration tries the following linker flags to find them.
-# If none of these work, add a working DBLIB line to configure.local,
-# disabling autodetection for library directories.
+# Autoconfiguration tries the following linker flags to find the
+# SQLite3 library installed on your system. If none of these work,
+# set the following variable to specify the required linker flags.
-DBLIB="-lsqlite3"
-DBLIB="-lsqlite3 -lutil"
-DBLIB="-L/usr/local/lib -lsqlite3"
+LD_SQLITE3="-lsqlite3"
+LD_SQLITE3="-L/usr/local/lib -lsqlite3"
# When library autodetection decides to use -L/usr/local/lib,
# -I/usr/local/include is automatically added to CFLAGS.
-# If you manually set DBLIB to something including -L/usr/local/lib,
+# If you manually set LD_SQLITE3 to something including -L/usr/local/lib,
# chances are you will also need the following line:
CFLAGS="${CFLAGS} -I/usr/local/include"
@@ -218,27 +236,45 @@ CGIBINDIR="${WWWPREFIX}/cgi-bin"
CC=cc
+# IBM AIX may need:
+
+CC=xlc
+
# The default compiler flags are:
CFLAGS="-g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings"
+# IBM AIX xlc does not support -W; in that case, please use:
+
+CFLAGS="-g"
+
# In rare cases, it may be required to skip individual automatic tests.
# Each of the following variables can be set to 0 (test will not be run
# and will be regarded as failed) or 1 (test will not be run and will
# be regarded as successful).
HAVE_DIRENT_NAMLEN=0
-HAVE_FGETLN=0
+HAVE_ERR=0
HAVE_FTS=0
+HAVE_GETLINE=0
HAVE_GETSUBOPT=0
+HAVE_ISBLANK=0
+HAVE_MKDTEMP=0
HAVE_MMAP=0
+HAVE_PLEDGE=0
+HAVE_PROGNAME=0
HAVE_REALLOCARRAY=0
+HAVE_REWB_BSD=0
+HAVE_REWB_SYSV=0
HAVE_STRCASESTR=0
+HAVE_STRINGLIST=0
HAVE_STRLCAT=0
HAVE_STRLCPY=0
HAVE_STRPTIME=0
HAVE_STRSEP=0
HAVE_STRTONUM=0
+HAVE_VASPRINTF=0
+HAVE_WCHAR=0
HAVE_SQLITE3=0
HAVE_SQLITE3_ERRSTR=0
diff --git a/contrib/mdocml/demandoc.c b/contrib/mdocml/demandoc.c
index 13b7890..c33fd89 100644
--- a/contrib/mdocml/demandoc.c
+++ b/contrib/mdocml/demandoc.c
@@ -1,4 +1,4 @@
-/* $Id: demandoc.c,v 1.26 2016/01/08 02:53:13 schwarze Exp $ */
+/* $Id: demandoc.c,v 1.27 2016/07/09 15:24:19 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -20,7 +20,6 @@
#include <assert.h>
#include <ctype.h>
-#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/contrib/mdocml/libmandoc.h b/contrib/mdocml/libmandoc.h
index 939ec83..9ed8f15 100644
--- a/contrib/mdocml/libmandoc.h
+++ b/contrib/mdocml/libmandoc.h
@@ -1,4 +1,4 @@
-/* $Id: libmandoc.h,v 1.62 2015/11/07 14:01:16 schwarze Exp $ */
+/* $Id: libmandoc.h,v 1.63 2016/07/07 19:19:01 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -38,7 +38,6 @@ struct tbl_span;
struct eqn;
struct roff;
struct roff_man;
-struct roff_node;
void mandoc_msg(enum mandocerr, struct mparse *,
int, int, const char *);
diff --git a/contrib/mdocml/main.c b/contrib/mdocml/main.c
index 2fc2e1e..527db24 100644
--- a/contrib/mdocml/main.c
+++ b/contrib/mdocml/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.262 2016/01/08 02:53:13 schwarze Exp $ */
+/* $Id: main.c,v 1.269 2016/07/12 05:18:38 kristaps Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014-2016 Ingo Schwarze <schwarze@openbsd.org>
@@ -30,11 +30,15 @@
#include <errno.h>
#include <fcntl.h>
#include <glob.h>
+#if HAVE_SANDBOX_INIT
+#include <sandbox.h>
+#endif
#include <signal.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include "mandoc_aux.h"
@@ -123,9 +127,9 @@ main(int argc, char *argv[])
unsigned char *uc;
struct manpage *res, *resp;
char *conf_file, *defpaths;
- size_t isec, i, sz;
+ const char *sec;
+ size_t i, sz;
int prio, best_prio;
- char sec;
enum outmode outmode;
int fd;
int show_usage;
@@ -158,6 +162,11 @@ main(int argc, char *argv[])
err((int)MANDOCLEVEL_SYSERR, "pledge");
#endif
+#if HAVE_SANDBOX_INIT
+ if (sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, NULL) == -1)
+ errx((int)MANDOCLEVEL_SYSERR, "sandbox_init");
+#endif
+
/* Search options. */
memset(&conf, 0, sizeof(conf));
@@ -389,7 +398,7 @@ main(int argc, char *argv[])
if (outmode == OUTMODE_ONE) {
argc = 1;
- best_prio = 10;
+ best_prio = 20;
} else if (outmode == OUTMODE_ALL)
argc = (int)sz;
@@ -405,11 +414,13 @@ main(int argc, char *argv[])
res[i].output);
else if (outmode == OUTMODE_ONE) {
/* Search for the best section. */
- isec = strcspn(res[i].file, "123456789");
- sec = res[i].file[isec];
- if ('\0' == sec)
+ sec = res[i].file;
+ sec += strcspn(sec, "123456789");
+ if (sec[0] == '\0')
continue;
- prio = sec_prios[sec - '1'];
+ prio = sec_prios[sec[0] - '1'];
+ if (sec[1] != '/')
+ prio += 10;
if (prio >= best_prio)
continue;
best_prio = prio;
@@ -476,7 +487,7 @@ main(int argc, char *argv[])
conf.output.synopsisonly);
if (argc > 1 && curp.outtype <= OUTT_UTF8)
- ascii_sepline(curp.outdata);
+ terminal_sepline(curp.outdata);
} else if (rc < MANDOCLEVEL_ERROR)
rc = MANDOCLEVEL_ERROR;
@@ -661,8 +672,8 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
found:
#if HAVE_SQLITE3
- warnx("outdated mandoc.db lacks %s(%s) entry, run makewhatis %s",
- name, sec, paths->paths[ipath]);
+ warnx("outdated mandoc.db lacks %s(%s) entry, run %s %s",
+ name, sec, BINM_MAKEWHATIS, paths->paths[ipath]);
#endif
*res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage));
page = *res + (*ressz - 1);
@@ -681,7 +692,7 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
int argc, char **argv, struct manpage **res, size_t *ressz)
{
const char *const sections[] =
- {"1", "8", "6", "2", "3", "3p", "5", "7", "4", "9"};
+ {"1", "8", "6", "2", "3", "5", "7", "4", "9", "3p"};
const size_t nsec = sizeof(sections)/sizeof(sections[0]);
size_t ipath, isec, lastsz;
@@ -1018,6 +1029,7 @@ mmsg(enum mandocerr t, enum mandoclevel lvl,
static pid_t
spawn_pager(struct tag_files *tag_files)
{
+ const struct timespec timeout = { 0, 100000000 }; /* 0.1s */
#define MAX_PAGER_ARGS 16
char *argv[MAX_PAGER_ARGS];
const char *pager;
@@ -1051,11 +1063,11 @@ spawn_pager(struct tag_files *tag_files)
break;
}
- /* For more(1) and less(1), use the tag file. */
+ /* For less(1), use the tag file. */
if ((cmdlen = strlen(argv[0])) >= 4) {
cp = argv[0] + cmdlen - 4;
- if (strcmp(cp, "less") == 0 || strcmp(cp, "more") == 0) {
+ if (strcmp(cp, "less") == 0) {
argv[argc++] = mandoc_strdup("-T");
argv[argc++] = tag_files->tfn;
}
@@ -1067,8 +1079,6 @@ spawn_pager(struct tag_files *tag_files)
case -1:
err((int)MANDOCLEVEL_SYSERR, "fork");
case 0:
- /* Set pgrp in both parent and child to avoid racing exec. */
- (void)setpgid(0, 0);
break;
default:
(void)setpgid(pager_pid, 0);
@@ -1087,6 +1097,12 @@ spawn_pager(struct tag_files *tag_files)
err((int)MANDOCLEVEL_SYSERR, "pager stdout");
close(tag_files->ofd);
close(tag_files->tfd);
+
+ /* Do not start the pager before controlling the terminal. */
+
+ while (tcgetpgrp(STDIN_FILENO) != getpid())
+ nanosleep(&timeout, NULL);
+
execvp(argv[0], argv);
err((int)MANDOCLEVEL_SYSERR, "exec %s", argv[0]);
}
diff --git a/contrib/mdocml/main.h b/contrib/mdocml/main.h
index e9e7e86..a53df93 100644
--- a/contrib/mdocml/main.h
+++ b/contrib/mdocml/main.h
@@ -1,4 +1,4 @@
-/* $Id: main.h,v 1.24 2015/11/07 14:01:16 schwarze Exp $ */
+/* $Id: main.h,v 1.25 2016/07/08 22:29:05 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -43,7 +43,6 @@ void *locale_alloc(const struct manoutput *);
void *utf8_alloc(const struct manoutput *);
void *ascii_alloc(const struct manoutput *);
void ascii_free(void *);
-void ascii_sepline(void *);
void *pdf_alloc(const struct manoutput *);
void *ps_alloc(const struct manoutput *);
@@ -51,3 +50,4 @@ void pspdf_free(void *);
void terminal_mdoc(void *, const struct roff_man *);
void terminal_man(void *, const struct roff_man *);
+void terminal_sepline(void *);
diff --git a/contrib/mdocml/man.1 b/contrib/mdocml/man.1
index f29360b..0a7ae6d 100644
--- a/contrib/mdocml/man.1
+++ b/contrib/mdocml/man.1
@@ -1,4 +1,4 @@
-.\" $Id: man.1,v 1.16 2015/09/21 09:59:02 schwarze Exp $
+.\" $Id: man.1,v 1.17 2016/07/01 20:24:04 schwarze Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -31,7 +31,7 @@
.\"
.\" @(#)man.1 8.2 (Berkeley) 1/2/94
.\"
-.Dd $Mdocdate: September 21 2015 $
+.Dd $Mdocdate: July 1 2016 $
.Dt MAN 1
.Os
.Sh NAME
@@ -209,13 +209,9 @@ architecture whilst using another.
This option overrides the
.Ev MACHINE
environment variable.
-.It Xo
-.Op Fl s
-.Ar section
-.Xc
-Restricts the directories that
-.Nm
-will search to a specific section.
+.It Oo Fl s Oc Ar section
+Only select manuals from the specified
+.Ar section .
The currently available sections are:
.Pp
.Bl -tag -width "localXXX" -offset indent -compact
@@ -225,9 +221,7 @@ General commands
.It 2
System calls and error numbers.
.It 3
-Libraries.
-.It 3f
-Fortran programmer's reference guide.
+Library functions.
.It 3p
.Xr perl 1
programmer's reference guide.
@@ -238,30 +232,12 @@ File formats.
.It 6
Games.
.It 7
-Miscellaneous.
+Miscellaneous information.
.It 8
System maintenance and operation commands.
.It 9
Kernel internals.
-.It X11
-An alias for X11R6.
-.It X11R6
-X Window System.
-.It local
-Pages located in
-.Pa /usr/local .
-.It n
-Tcl/Tk commands.
.El
-.Pp
-The
-.Nm
-configuration file,
-.Xr man.conf 5 ,
-specifies the possible
-.Ar section
-values, and their search order.
-Additional sections may be specified.
.It Fl T Ar output
Select the output format.
The default is
diff --git a/contrib/mdocml/man.cgi.3 b/contrib/mdocml/man.cgi.3
new file mode 100644
index 0000000..e7c1d2f
--- /dev/null
+++ b/contrib/mdocml/man.cgi.3
@@ -0,0 +1,287 @@
+.\" $Id: man.cgi.3,v 1.2 2016/07/07 19:19:01 schwarze Exp $
+.\"
+.\" Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
+.\"
+.\" 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.
+.\"
+.Dd $Mdocdate: July 7 2016 $
+.Dt MAN.CGI 3
+.Os
+.Sh NAME
+.Nm man.cgi
+.Nd internals of the CGI program to search and display manual pages
+.Sh DESCRIPTION
+The source code of
+.Xr man.cgi 8
+is organized in four levels:
+.Pp
+.Bl -enum -compact
+.It
+.Sx Top level
+.It
+.Sx Page generators
+.It
+.Sx Result generators
+.It
+.Sx Utility routines
+.El
+.Ss Top level
+The top level of
+.Xr man.cgi 8
+consists of the
+.Fn main
+program and a few parser routines.
+.Bl -tag -width 1n
+.It Ft int Fn main void
+The main program
+.Bl -dash -compact
+.It
+limits execution time;
+.It
+changes to
+.Dv MAN_DIR ,
+the data directory containing all the manual trees;
+.It
+calls
+.Fn parse_manpath_conf ;
+.It
+if
+.Ev PATH_INFO
+is empty, calls
+.Fn parse_query_string ;
+otherwise,
+calls
+.Fn parse_path_info ;
+.It
+validates the manpath and the architecture;
+.It
+calls the appropriate one among the
+.Sx Page generators .
+.El
+.It Ft void Fn parse_manpath_conf "struct req *req"
+Parses and validates
+.Pa manpath.conf
+and fills
+.Va req->p
+and
+.Va req->psz .
+.It Ft void Fn parse_path_info "struct req *req" "const char *path"
+Parses and validates
+.Ev PATH_INFO ,
+clears
+.Va req->isquery ,
+and fills
+.Va req->q .
+.It Ft void Fn parse_query_string "struct req *req" "const char *qs"
+Parses and validates
+.Ev QUERY_STRING ,
+sets
+.Va req->isquery ,
+and fills
+.Va req->q .
+This function is the only user of the utility functions
+.Fn http_decode
+and
+.Fn set_query_attr .
+.El
+.Ss Page generators
+The purpose of each page generator is to print a complete HTML page,
+starting with the HTTP headers and continuing to the page footer.
+Before starting HTML output with
+.Fn resp_begin_html ,
+some page generators do some preparatory work, for example to decide
+which page to show.
+Each page generator ends with a call to
+.Fn resp_end_html .
+.Bl -tag -width 1n
+.It Ft void Fn pg_show "struct req *req" "const char *fullpath"
+This page generator is used when
+.Ev PATH_INFO
+contains the complete path to a manual page including manpath,
+section directory, optional architecture subdirectory, manual name
+and section number suffix.
+It validates the manpath, changes into it, validate the filename,
+and then calls
+.Fn resp_begin_html ,
+.Fn resp_searchform ,
+.Fn resp_show ,
+and
+.Fn resp_end_html
+in that order.
+.It Ft void Fn pg_search "const struct req *req"
+This page generator is used when
+.Ev PATH_INFO
+contains a search query in short format or when
+.Ev PATH_INFO
+is empty and a
+.Ev QUERY_STRING
+is provided.
+It changes into the manpath and calls
+.Xr mansearch 3 .
+Depending on the result, it calls either
+.Fn pg_noresult
+or
+.Fn pg_searchres .
+.It Ft void Fn pg_noresult "const struct req *req" "const char *msg"
+This function calls
+.Fn resp_begin_html ,
+.Fn resp_searchform ,
+prints the
+.Fa msg
+passed to it, and calls
+.Fn resp_end_html .
+.It Ft void Fn pg_searchres "const struct req *req" "struct manpage *r"\
+ "size_t sz"
+This function first validates the filenames found.
+If
+.Ev QUERY_STRING
+was used and there is exactly one result,
+it writes an HTTP redirect to that result.
+Otherwise, it writes an HTML result page beginning with
+.Fn resp_begin_html
+and
+.Fn resp_searchform .
+If there is more than one result, it writes a list of links
+to all the results.
+If it was a
+.Xr man 1
+rather than an
+.Xr apropos 1
+query or if there is only one single result, it calls
+.Fn resp_show .
+Finally, it calls
+.Fn resp_end_html .
+.It Ft void Fn pg_index "const struct req *req"
+This page generator is used when
+.Ev PATH_INFO
+and
+.Ev QUERY_STRING
+are both empty.
+It calls
+.Fn resp_begin_html
+and
+.Fn resp_searchform ,
+writes links to help pages, and calls
+.Fn resp_end_html .
+.It Ft void Fn pg_error_badrequest "const char *msg"
+This page generator is used when
+.Fn main
+or
+.Fn pg_show
+detect an invalid URI.
+It calls
+.Fn resp_begin_html ,
+prints the
+.Fa msg
+provided, and calls
+.Fn resp_end_html .
+.It Ft void Fn pg_error_internal void
+This page generator is used by various functions when errors are
+detected in the
+.Pa manpath.conf
+configuration file, in
+.Xr mandoc.db 5
+databases, in the
+.Xr mandoc 3
+parser, in file system permissions, or when setting up timeouts.
+It calls
+.Fn resp_begin_html ,
+prints
+.Qq "Internal Server Error" ,
+and calls
+.Fn resp_end_html .
+Before calling
+.Fn pg_error_internal ,
+call
+.Xr warn 3
+or
+.Xr warnx 3
+to log the reason of the error to the
+.Xr httpd 8
+server log file.
+.El
+.Ss Result generators
+The purpose of result generators is to print a chunk of HTML code.
+When they print untrusted strings or characters,
+.Fn html_print
+and
+.Fn html_putchar
+are used.
+The highest level result generators are:
+.Bl -tag -width 1n
+.It Ft void Fn resp_begin_html "int code" "const char *msg"
+This generator calls
+.Fn resp_begin_http
+to print the HTTP headers, then prints the HTML header up to the
+opening tag of the <body> element, then copies the file
+.Pa header.html
+to the output, if it exists and is readable.
+.It Ft void Fn resp_searchform "const struct req *req" "enum focus focus"
+This generator prints a search form, filling it with data
+from the provided request object.
+If the
+.Fa focus
+argument is
+.Dv FOCUS_QUERY ,
+it sets the document's autofocus to the query input box.
+.It Ft void Fn resp_show "const struct req *req" "const char *file"
+This wrapper dispatches to either
+.Fn resp_catman
+or
+.Fn resp_format ,
+depending on whether
+.Ar file
+starts with
+.Pa cat
+or
+.Pa man ,
+respectively.
+.It Ft void Fn resp_catman "const struct req *req" "const char *file"
+This generator translates a preformatted, backspace-encoded manual
+page to HTML and prints it to the output.
+.It Ft void Fn resp_format "const struct req *req" "const char *file"
+This generator formats a manual page on the standard output,
+using the functions documented in
+.Xr mchars_alloc 3
+and
+.Xr mandoc 3 .
+.It Ft void Fn resp_end_html void
+This generator copies the file
+.Pa footer.html
+to the output, if it exists and is readable,
+and closes the <body> and <html> elements.
+.El
+.Ss Utility routines
+These functions take a string and return 1 if it is valid, or 0 otherwise.
+.Bl -tag -width 1n
+.It Ft int Fn validate_urifrag "const char *frag"
+Checks that the string only contains alphanumeric ASCII characters,
+dashes, dots, slashes, and underscores.
+.It Ft int Fn validate_manpath "const struct req *req" "const char* manpath"
+Checks that the string is either
+.Qq mandoc
+or one of the manpaths configured in
+.Pa manpath.conf .
+.It Ft int Fn validate_filename "const char *file"
+Checks that the string starts with
+.Qq man
+or
+.Qq cat
+and does not ascend to parent directories.
+.El
+.Sh SEE ALSO
+.Xr mandoc 3 ,
+.Xr mansearch 3 ,
+.Xr mchars_alloc 3 ,
+.Xr mandoc.db 5 ,
+.Xr man.cgi 8
diff --git a/contrib/mdocml/man.cgi.8 b/contrib/mdocml/man.cgi.8
index 2e54dbf..0e1b60d 100644
--- a/contrib/mdocml/man.cgi.8
+++ b/contrib/mdocml/man.cgi.8
@@ -1,6 +1,6 @@
-.\" $Id: man.cgi.8,v 1.13 2015/11/05 20:55:41 schwarze Exp $
+.\" $Id: man.cgi.8,v 1.20 2016/07/11 22:48:37 schwarze Exp $
.\"
-.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: November 5 2015 $
+.Dd $Mdocdate: July 11 2016 $
.Dt MAN.CGI 8
.Os
.Sh NAME
@@ -26,9 +26,9 @@ The
CGI program searches for manual pages on a WWW server
and displays them to HTTP clients,
providing functionality equivalent to the
-.Xr apropos 1
-and
.Xr man 1
+and
+.Xr apropos 1
utilities.
It can use multiple manual trees in parallel.
.Ss HTML search interface
@@ -51,20 +51,15 @@ The effect of prepending a backslash to another character is undefined;
in the current implementation, it has no effect.
.It
A
-.Dq Submit
-button to send a search request from the client to the server.
-.It
-A
-.Dq Reset
-button to undo any changes to the input boxes and the dropdown menus
-and reset them to the values contained in the
-.Ev QUERY_STRING .
-.It
-Radio buttons to select pages either by name like in
.Xr man 1
-or using
+submit button.
+The string in the input box is interpreted as the name of a manual page.
+.It
+An
.Xr apropos 1
-queries.
+submit button.
+The string in the input box is interpreted as a search
+.Ar expression .
.It
A dropdown menu to optionally select a manual section.
If one is provided, it has the same effect as the
@@ -162,9 +157,7 @@ Configure your web server to execute CGI programs located in
.Pa /cgi-bin .
When using
.Ox
-.Xr httpd 8
-or
-.Xr nginx 8 ,
+.Xr httpd 8 ,
the
.Xr slowcgi 8
proxy daemon is needed to translate FastCGI requests to plain old CGI.
@@ -183,31 +176,42 @@ Only useful for running on www.openbsd.org to deal with old URIs containing
.Qq "manpath=OpenBSD "
where the blank character has to be translated to a hyphen.
When compiling for other sites, this definition can be deleted.
-.It Ev CSS_DIR
-An optional path to the directory containing the CSS files,
+.It Dv CSS_DIR
+An optional file system path to the directory containing the file
+.Pa mandoc.css ,
to be specified relative to the server's document root,
and to be specified without a trailing slash.
-When not specified, the CSS files
-are assumed to be in the document root.
+When empty, the CSS file is assumed to be in the document root.
+Otherwise, a leading slash is needed.
This is used in generated HTML code.
-.It Ev CUSTOMIZE_TITLE
+.It Dv CUSTOMIZE_TITLE
An ASCII string to be used for the HTML <TITLE> element.
-.It Ev HTTP_HOST
+.It Dv HTTP_HOST
The FQDN of the (possibly virtual) host the HTTP server is running on.
This is used for
.Ic Location:
headers in HTTP 303 responses.
-.It Ev MAN_DIR
-A path to the
+.It Dv MAN_DIR
+A file system path to the
.Nm
-data directory to be used instead of
-.Pa /var/www/man ,
-relative to the web server
+data directory relative to the web server
.Xr chroot 2
-directory, to be specified without a trailing slash.
-This is prepended to the manpath when opening
+directory, to be specified with a leading slash and without a trailing slash.
+It needs to have at least one component; the root directory cannot be used
+for this purpose.
+The files
+.Pa manpath.conf ,
+.Pa header.html ,
+and
+.Pa footer.html
+are looked up in this directory.
+It is also prepended to the manpath when opening
.Xr mandoc.db 5
and manual page files.
+.It Dv SCRIPT_NAME
+The initial component of URIs, to be specified without leading
+and trailing slashes.
+It can be empty.
.El
.Pp
After editing
@@ -216,13 +220,16 @@ run
.Pp
.Dl make man.cgi
.Pp
-and copy the files to the proper locations.
-Reading the
-.Cm installcgi
-target in the
-.Pa Makefile
-can help with that, but do not run it without carefully checking it
-because the directory layouts of web servers vary greatly.
+and copy the resulting binary to the proper location,
+for example using the command:
+.Pp
+.Dl make installcgi
+.Pp
+In addition to that, make sure the default manpath contains the files
+.Pa man1/apropos.1
+and
+.Pa man8/man.cgi.8 ,
+or the documentation links at the bottom of the index page will not work.
.Ss URI interface
.Nm
uniform resource identifiers are not needed for interactive use,
@@ -234,14 +241,22 @@ The
.Cm http://
protocol specifier.
.It
-The host name and a following slash.
+The host name.
.It
-The path to the program, normally
-.Pa cgi-bin/man.cgi/ .
+The
+.Dv SCRIPT_NAME ,
+preceded by a slash unless empty.
.It
To show a single page, a slash, the manpath, another slash,
and the name of the requested file, for example
.Pa /OpenBSD-current/man1/mandoc.1 .
+This can be abbreviated according to the following syntax:
+.Sm off
+.Op / Ar manpath
+.Op / Cm man Ar sec
+.Op / Ar arch
+.Pf / Ar name Op \&. Ar sec
+.Sm on
.It
For searches, a query string starting with a question mark
and consisting of
@@ -295,13 +310,20 @@ the underscore
.Pq Sq _
.El
.Pp
-In particular, this applies to the
-.Ev SCRIPT_NAME ,
-to all manpaths, and to all architecture names.
+In particular, this applies to all manpaths and architecture names.
.Sh ENVIRONMENT
The web server may pass the following CGI variables to
.Nm :
.Bl -tag -width Ds
+.It Ev SCRIPT_NAME
+The initial part of the URI passed from the client to the server,
+starting after the server's host name and ending before
+.Ev PATH_INFO .
+This is ignored by
+.Nm .
+When constructing URIs for links and redirections, the
+.Dv SCRIPT_NAME
+preprocessor constant is used instead.
.It Ev PATH_INFO
The final part of the URI path passed from the client to the server,
starting after the
@@ -317,17 +339,6 @@ It is the final part of the URI, after the question mark.
It is used by the
.Cm search
page to acquire the named parameters it needs.
-.It Ev SCRIPT_NAME
-The path to the
-.Nm
-binary relative to the server root, usually
-.Pa /cgi-bin/man.cgi .
-This is used for generating URIs to be embedded
-in generated HTML code and HTTP headers.
-If this contains any character not contained in the
-.Sx Restricted character set ,
-.Nm
-reports an internal server error and exits without doing anything.
.El
.Sh FILES
.Bl -tag -width Ds
@@ -337,13 +348,18 @@ Default web server
directory.
All the following paths are specified relative to this directory.
.It Pa /cgi-bin/man.cgi
-The path to the
+The usual file system path to the
.Nm
-program relative to the server root.
-Can be overridden by
-.Ev SCRIPT_NAME .
+program inside the web server
+.Xr chroot 2
+directory.
+A different name can be chosen, but in any case, it needs to be configured in
+.Xr httpd.conf 5 .
.It Pa /htdocs
-The path to the server document root relative to the server root.
+The file system path to the server document root directory
+relative to the server
+.Xr chroot 2
+directory.
This is part of the web server configuration and not specific to
.Nm .
.It Pa /htdocs/mandoc.css
@@ -355,11 +371,7 @@ Default
.Nm
data directory containing all the manual trees.
Can be overridden by
-.Ev MAN_DIR .
-.It Pa /man/mandoc/man1/apropos.1 , /man/mandoc/man8/man.cgi.8
-Manual pages documenting
-.Nm
-itself, linked from the index page.
+.Dv MAN_DIR .
.It Pa /man/manpath.conf
The list of available manpaths, one per line.
If any of the lines in this file contains a slash
diff --git a/contrib/mdocml/mandoc.3 b/contrib/mdocml/mandoc.3
index 61012ed..18b5707 100644
--- a/contrib/mdocml/mandoc.3
+++ b/contrib/mdocml/mandoc.3
@@ -1,4 +1,4 @@
-.\" $Id: mandoc.3,v 1.36 2016/01/08 17:48:09 schwarze Exp $
+.\" $Id: mandoc.3,v 1.37 2016/07/07 19:19:01 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,18 +15,16 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: January 8 2016 $
+.Dd $Mdocdate: July 7 2016 $
.Dt MANDOC 3
.Os
.Sh NAME
.Nm mandoc ,
-.Nm man_deroff ,
-.Nm man_meta ,
+.Nm deroff ,
+.Nm mandocmsg ,
.Nm man_mparse ,
-.Nm man_node ,
-.Nm mdoc_deroff ,
-.Nm mdoc_meta ,
-.Nm mdoc_node ,
+.Nm man_validate ,
+.Nm mdoc_validate ,
.Nm mparse_alloc ,
.Nm mparse_free ,
.Nm mparse_getkeep ,
@@ -91,8 +89,7 @@
.Ft void
.Fo mparse_result
.Fa "struct mparse *parse"
-.Fa "struct mdoc **mdoc"
-.Fa "struct man **man"
+.Fa "struct roff_man **man"
.Fa "char **sodest"
.Fc
.Ft "const char *"
@@ -103,45 +100,33 @@
.Fo mparse_strlevel
.Fa "enum mandoclevel"
.Fc
-.In sys/types.h
-.In mandoc.h
-.In mdoc.h
+.In roff.h
.Ft void
-.Fo mdoc_deroff
+.Fo deroff
.Fa "char **dest"
-.Fa "const struct mdoc_node *node"
-.Fc
-.Ft "const struct mdoc_meta *"
-.Fo mdoc_meta
-.Fa "const struct mdoc *mdoc"
-.Fc
-.Ft "const struct mdoc_node *"
-.Fo mdoc_node
-.Fa "const struct mdoc *mdoc"
+.Fa "const struct roff_node *node"
.Fc
+.In sys/types.h
+.In mandoc.h
+.In mdoc.h
.Vt extern const char * const * mdoc_argnames;
.Vt extern const char * const * mdoc_macronames;
+.Ft void
+.Fo mdoc_validate
+.Fa "struct roff_man *mdoc"
+.Fc
.In sys/types.h
.In mandoc.h
.In man.h
-.Ft void
-.Fo man_deroff
-.Fa "char **dest"
-.Fa "const struct man_node *node"
-.Fc
-.Ft "const struct man_meta *"
-.Fo man_meta
-.Fa "const struct man *man"
-.Fc
+.Vt extern const char * const * man_macronames;
.Ft "const struct mparse *"
.Fo man_mparse
-.Fa "const struct man *man"
+.Fa "const struct roff_man *man"
.Fc
-.Ft "const struct man_node *"
-.Fo man_node
-.Fa "const struct man *man"
+.Ft void
+.Fo man_validate
+.Fa "struct roff_man *man"
.Fc
-.Vt extern const char * const * man_macronames;
.Sh DESCRIPTION
The
.Nm mandoc
@@ -182,10 +167,24 @@ close it with
retrieve the syntax tree with
.Fn mparse_result ;
.It
-iterate over parse nodes with
-.Fn mdoc_node
+depending on whether the
+.Fa macroset
+member of the returned
+.Vt struct roff_man
+is
+.Dv MACROSET_MDOC
+or
+.Dv MACROSET_MAN ,
+validate it with
+.Fn mdoc_validate
or
-.Fn man_node ;
+.Fn man_validate ,
+respectively;
+.It
+iterate over parse nodes with starting from the
+.Fa first
+member of the returned
+.Vt struct roff_man ;
.It
free all allocated memory with
.Fn mparse_free
@@ -193,7 +192,7 @@ and
.Xr mchars_free 3 ,
or invoke
.Fn mparse_reset
-and parse new files.
+and go back to step 2 to parse new files.
.El
.Sh REFERENCE
This section documents the functions, types, and variables available
@@ -211,6 +210,9 @@ An error or warning message during parsing.
A classification of an
.Vt "enum mandocerr"
as regards system operation.
+See the DIAGNOSTICS section in
+.Xr mandoc 1
+regarding the meanings of the levels.
.It Vt "struct mparse"
An opaque pointer to a running parse sequence.
Created with
@@ -226,67 +228,37 @@ messages emitted by the parser.
.El
.Ss Functions
.Bl -ohang
-.It Fn man_deroff
+.It Fn deroff
Obtain a text-only representation of a
-.Vt struct man_node ,
+.Vt struct roff_node ,
including text contained in its child nodes.
-To be used on children of the pointer returned from
-.Fn man_node .
+To be used on children of the
+.Fa first
+member of
+.Vt struct roff_man .
When it is no longer needed, the pointer returned from
-.Fn man_deroff
+.Fn deroff
can be passed to
.Xr free 3 .
-.It Fn man_meta
-Obtain the meta-data of a successful
-.Xr man 7
-parse.
-This may only be used on a pointer returned by
-.Fn mparse_result .
-Declared in
-.In man.h ,
-implemented in
-.Pa man.c .
.It Fn man_mparse
Get the parser used for the current output.
Declared in
.In man.h ,
implemented in
.Pa man.c .
-.It Fn man_node
-Obtain the root node of a successful
-.Xr man 7
-parse.
-This may only be used on a pointer returned by
+.It Fn man_validate
+Validate the
+.Dv MACROSET_MAN
+parse tree obtained with
.Fn mparse_result .
Declared in
.In man.h ,
implemented in
.Pa man.c .
-.It Fn mdoc_deroff
-Obtain a text-only representation of a
-.Vt struct mdoc_node ,
-including text contained in its child nodes.
-To be used on children of the pointer returned from
-.Fn mdoc_node .
-When it is no longer needed, the pointer returned from
-.Fn mdoc_deroff
-can be passed to
-.Xr free 3 .
-.It Fn mdoc_meta
-Obtain the meta-data of a successful
-.Xr mdoc
-parse.
-This may only be used on a pointer returned by
-.Fn mparse_result .
-Declared in
-.In mdoc.h ,
-implemented in
-.Pa mdoc.c .
-.It Fn mdoc_node
-Obtain the root node of a successful
-.Xr mdoc
-parse.
-This may only be used on a pointer returned by
+.It Fn mdoc_validate
+Validate the
+.Dv MACROSET_MDOC
+parse tree obtained with
.Fn mparse_result .
Declared in
.In mdoc.h ,
@@ -335,6 +307,9 @@ A callback function to handle errors and warnings.
See
.Pa main.c
for an example.
+If printing of error messages is not desired,
+.Dv NULL
+may be passed.
.It Ar defos
A default string for the
.Xr mdoc 7
@@ -343,6 +318,9 @@ macro, overriding the
.Dv OSNAME
preprocessor definition and the results of
.Xr uname 3 .
+Passing
+.Dv NULL
+sets no default.
.El
.Pp
The same parser may be used for multiple files so long as
@@ -421,7 +399,7 @@ implemented in
.Pa read.c .
.It Fn mparse_result
Obtain the result of a parse.
-One of the three pointers will be filled in.
+One of the two pointers will be filled in.
Declared in
.In mandoc.h ,
implemented in
@@ -442,13 +420,19 @@ implemented in
.Ss Variables
.Bl -ohang
.It Va man_macronames
-The string representation of a man macro as indexed by
+The string representation of a
+.Xr man 7
+macro as indexed by
.Vt "enum mant" .
.It Va mdoc_argnames
-The string representation of a mdoc macro argument as indexed by
+The string representation of an
+.Xr mdoc 7
+macro argument as indexed by
.Vt "enum mdocargt" .
.It Va mdoc_macronames
-The string representation of a mdoc macro as indexed by
+The string representation of an
+.Xr mdoc 7
+macro as indexed by
.Vt "enum mdoct" .
.El
.Sh IMPLEMENTATION NOTES
@@ -492,15 +476,15 @@ This AST is governed by the ontological rules dictated in
and derives its terminology accordingly.
.Pp
The AST is composed of
-.Vt struct man_node
+.Vt struct roff_node
nodes with element, root and text types as declared by the
.Va type
field.
Each node also provides its parse point (the
.Va line ,
-.Va sec ,
+.Va pos ,
and
-.Va pos
+.Va sec
fields), its position in the tree (the
.Va parent ,
.Va child ,
@@ -544,16 +528,16 @@ are described simply as
.Qq elements .
.Pp
The AST is composed of
-.Vt struct mdoc_node
+.Vt struct roff_node
nodes with block, head, body, element, root and text types as declared
by the
.Va type
field.
Each node also provides its parse point (the
.Va line ,
-.Va sec ,
+.Va pos ,
and
-.Va pos
+.Va sec
fields), its position in the tree (the
.Va parent ,
.Va child ,
@@ -670,9 +654,13 @@ consistent across troff implementations, especially when using multiple
levels of badly-nested blocks.
.Sh SEE ALSO
.Xr mandoc 1 ,
+.Xr man.cgi 3 ,
.Xr mandoc_escape 3 ,
+.Xr mandoc_headers 3 ,
.Xr mandoc_malloc 3 ,
+.Xr mansearch 3 ,
.Xr mchars_alloc 3 ,
+.Xr tbl 3 ,
.Xr eqn 7 ,
.Xr man 7 ,
.Xr mandoc_char 7 ,
@@ -680,7 +668,10 @@ levels of badly-nested blocks.
.Xr roff 7 ,
.Xr tbl 7
.Sh AUTHORS
+.An -nosplit
The
.Nm
library was written by
-.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
+and is maintained by
+.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
diff --git a/contrib/mdocml/mandoc.css b/contrib/mdocml/mandoc.css
index 38c5c58..9008506 100644
--- a/contrib/mdocml/mandoc.css
+++ b/contrib/mdocml/mandoc.css
@@ -1,4 +1,4 @@
-/* $Id: mandoc.css,v 1.1 2015/11/05 17:47:51 schwarze Exp $ */
+/* $Id: mandoc.css,v 1.2 2016/04/13 10:19:23 schwarze Exp $ */
/*
* This is an example style-sheet provided for mandoc(1) and the -Thtml
@@ -24,7 +24,8 @@ body > div.results { font-size: smaller; }
#mancgi input[name=expr] { width: 25%; }
.results td.title { vertical-align: top;
padding-right: 1em; }
-h1 { margin-bottom: 1ex; font-size: 110%; margin-left: -4ex; } /* Section header (Sh, SH). */
+h1 { margin-bottom: 1ex; font-size: 110% }
+div.section > h1 { margin-left: -4ex; } /* Section header (Sh, SH). */
h2 { margin-bottom: 1ex; font-size: 105%; margin-left: -2ex; } /* Sub-section header (Ss, SS). */
table { width: 100%; margin-top: 0ex; margin-bottom: 0ex; } /* All tables. */
td { vertical-align: top; } /* All table cells. */
diff --git a/contrib/mdocml/mandoc.db.5 b/contrib/mdocml/mandoc.db.5
index 60908bc..de6ea11 100644
--- a/contrib/mdocml/mandoc.db.5
+++ b/contrib/mdocml/mandoc.db.5
@@ -1,4 +1,4 @@
-.\" $Id: mandoc.db.5,v 1.3 2014/12/30 21:34:57 schwarze Exp $
+.\" $Id: mandoc.db.5,v 1.4 2016/07/07 14:35:48 schwarze Exp $
.\"
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: December 30 2014 $
+.Dd $Mdocdate: July 7 2016 $
.Dt MANDOC.DB 5
.Os
.Sh NAME
@@ -133,7 +133,6 @@ The same for
.Xr man 1 ,
.Xr sqlite3 1 ,
.Xr whatis 1 ,
-.Xr mansearch 3 ,
.Xr makewhatis 8
.Sh HISTORY
A manual page database
diff --git a/contrib/mdocml/mandoc_headers.3 b/contrib/mdocml/mandoc_headers.3
index 6c30e16..b8c204b 100644
--- a/contrib/mdocml/mandoc_headers.3
+++ b/contrib/mdocml/mandoc_headers.3
@@ -62,6 +62,11 @@ for
.Vt size_t .
Provides the utility functions documented in
.Xr mandoc_malloc 3 .
+.It Qq Pa mandoc_ohash.h
+Includes
+.In ohash.h
+and provides
+.Fn mandoc_ohash_init .
.It Qq Pa mandoc.h
Requires
.In sys/types.h
@@ -80,7 +85,6 @@ Provides
.Vt enum eqn_pilet ,
.Vt enum eqn_post ,
.Vt struct tbl_opts ,
-.Vt struct tbl_head ,
.Vt struct tbl_cell ,
.Vt struct tbl_row ,
.Vt struct tbl_dat ,
@@ -103,30 +107,30 @@ Uses the opaque type
from
.Pa read.c
for function prototypes.
-Uses the types
-.Vt struct mdoc
-from
-.Pa libmdoc.h
-and
-.Vt struct man
+Uses the type
+.Vt struct roff_man
from
-.Pa libman.h
-as opaque types for function prototypes.
+.Pa roff.h
+as an opaque type for function prototypes.
.It Qq Pa roff.h
Provides
.Vt enum mdoc_endbody ,
+.Vt enum roff_macroset ,
+.Vt enum roff_next ,
.Vt enum roff_sec ,
.Vt enum roff_type ,
+.Vt struct roff_man ,
.Vt struct roff_meta ,
-and
-.Vt struct roff_node .
+.Vt struct roff_node ,
+and the function
+.Fn deroff .
.Pp
Uses pointers to the types
.Vt struct mdoc_arg
and
.Vt union mdoc_data
from
-.Qq Pa mdoc.h
+.Pa mdoc.h
as opaque struct members.
.El
.Pp
@@ -139,51 +143,38 @@ Afterwards, any other mandoc headers can be included as needed.
Requires
.In sys/types.h
for
-.Vt size_t
-and
-.Qq Pa roff.h
-for
-.Vt enum roff_type .
+.Vt size_t .
.Pp
Provides
.Vt enum mdocargt ,
-.Vt enum mdoc_disp ,
-.Vt enum mdoc_list ,
.Vt enum mdoc_auth ,
+.Vt enum mdoc_disp ,
.Vt enum mdoc_font ,
+.Vt enum mdoc_list ,
.Vt struct mdoc_argv ,
.Vt struct mdoc_arg ,
-.Vt struct mdoc_bd ,
-.Vt struct mdoc_bl ,
.Vt struct mdoc_an ,
+.Vt struct mdoc_bd ,
.Vt struct mdoc_bf ,
+.Vt struct mdoc_bl ,
.Vt struct mdoc_rs ,
+.Vt union mdoc_data ,
and the functions
.Fn mdoc_*
described in
.Xr mandoc 3 .
.Pp
Uses the type
-.Vt struct mdoc
+.Vt struct roff_man
from
-.Pa libmdoc.h
+.Pa roff.h
as an opaque type for function prototypes.
-Uses pointers to the types
-.Vt struct tbl_span
-and
-.Vt struct eqn
-as opaque struct members.
.Pp
When this header is included, the same file should not include
.Pa libman.h
or
.Pa libroff.h .
.It Qq Pa man.h
-Requires
-.Qq Pa roff.h
-for
-.Vt enum roff_type .
-.Pp
Provides the functions
.Fn man_*
described in
@@ -195,15 +186,10 @@ from
.Pa read.c
for function prototypes.
Uses the type
-.Vt struct man
+.Vt struct roff_man
from
-.Pa libman.h
+.Pa roff.h
as an opaque type for function prototypes.
-Uses pointers to the types
-.Vt struct tbl_span
-and
-.Vt struct eqn
-as opaque struct members.
.Pp
When this header is included, the same file should not include
.Pa libmdoc.h
@@ -220,16 +206,11 @@ are included, the same file should not include any formatter headers.
Requires
.In sys/types.h
for
-.Vt size_t ,
-.Qq Pa mandoc.h
-for
-.Vt enum mandocerr ,
+.Vt size_t
and
-.Qq Pa roff.h
+.Qq Pa mandoc.h
for
-.Vt struct roff_meta
-and
-.Vt struct roff_node .
+.Vt enum mandocerr .
.Pp
Provides
.Vt enum rofferr ,
@@ -251,14 +232,42 @@ Uses the types
and
.Vt struct eqn
from
+.Pa mandoc.h
+and
+.Vt struct roff_man
+from
+.Pa roff.h
+as opaque types for function prototypes.
+.It Qq Pa roff_int.h
+Requires
+.Qq Pa roff.h
+for
+.Vt enum roff_type .
+.Pp
+Provides functions named
+.Fn roff_*
+to handle roff nodes and the two special functions
+.Fn man_breakscope
+and
+.Fn mdoc_argv_free
+because the latter two are needed by
+.Qq Pa roff.c .
+.Pp
+Uses the types
+.Vt struct eqn
+and
+.Vt struct tbl_span
+from
.Pa mandoc.h ,
-.Vt struct mdoc
+.Vt struct roff_man
+and
+.Vt struct roff_node
from
-.Pa libmdoc.h ,
+.Pa roff.h ,
and
-.Vt struct man
+.Vt struct mdoc_arg
from
-.Pa libman.h
+.Pa mdoc.h
as opaque types for function prototypes.
.It Qq Pa libmdoc.h
Requires
@@ -269,23 +278,24 @@ and
.Vt struct mdoc_* .
.Pp
Provides
-.Vt enum mdoc_next ,
.Vt enum margserr ,
.Vt enum mdelim ,
-.Vt struct mdoc ,
.Vt struct mdoc_macro ,
and many functions internal to the
.Xr mdoc 7
parser.
.Pp
-Uses the opaque types
+Uses the opaque type
.Vt struct mparse
from
-.Pa read.c
+.Pa read.c .
+Uses the types
+.Vt struct roff_man
and
-.Vt struct roff
+.Vt struct roff_node
from
-.Pa roff.c .
+.Pa roff.h
+as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
.Pa man.h ,
@@ -293,29 +303,19 @@ When this header is included, the same file should not include
or
.Pa libroff.h .
.It Qq Pa libman.h
-Requires
-.Qq Pa roff.h
-for
-.Vt struct roff_meta
-and
-.Vt struct roff_node .
-.Pp
Provides
-.Vt enum man_next ,
-.Vt struct man ,
-.Vt struct man_macro ,
-and many functions internal to the
+.Vt struct man_macro
+and some functions internal to the
.Xr man 7
parser.
.Pp
-Uses the opaque types
-.Vt struct mparse
-from
-.Pa read.c
+Uses the types
+.Vt struct roff_man
and
-.Vt struct roff
+.Vt struct roff_node
from
-.Pa roff.c .
+.Pa roff.h
+as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
.Pa mdoc.h ,
@@ -420,7 +420,7 @@ from
and
.Vt struct roff_meta
from
-.Qq Pa roff.h
+.Pa roff.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
@@ -456,18 +456,26 @@ When this header is included, the same file should not include
.Pa term.h
or
.Pa mansearch.h .
+.It Qq Pa tag.h
+Requires
+.In sys/types.h
+for
+.Vt size_t .
+.Pp
+Provides an interface to generate
+.Xr ctags 1
+files for the
+.Ic :t
+functionality mentioned in
+.Xr man 1 .
.It Qq Pa main.h
Provides the top level steering functions for all formatters.
.Pp
-Uses the types
-.Vt struct mdoc
-from
-.Pa libmdoc.h
-and
-.Vt struct man
+Uses the type
+.Vt struct roff_man
from
-.Pa libman.h
-as opaque types for function prototypes.
+.Pa roff.h
+as an opaque type for function prototypes.
.It Qq Pa manconf.h
Requires
.In sys/types.h
diff --git a/contrib/mdocml/mandoc_malloc.3 b/contrib/mdocml/mandoc_malloc.3
index c167984..ae3ca16 100644
--- a/contrib/mdocml/mandoc_malloc.3
+++ b/contrib/mdocml/mandoc_malloc.3
@@ -1,4 +1,4 @@
-.\" $Id: mandoc_malloc.3,v 1.1 2014/08/05 05:48:56 schwarze Exp $
+.\" $Id: mandoc_malloc.3,v 1.2 2016/07/07 19:19:01 schwarze Exp $
.\"
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: August 5 2014 $
+.Dd $Mdocdate: July 7 2016 $
.Dt MANDOC_MALLOC 3
.Os
.Sh NAME
@@ -26,8 +26,6 @@
.Nm mandoc_strndup ,
.Nm mandoc_asprintf
.Nd memory allocation function wrappers used in the mandoc library
-.Sh LIBRARY
-.Lb libmandoc
.Sh SYNOPSIS
.In sys/types.h
.In mandoc_aux.h
@@ -67,21 +65,18 @@
.Fa "..."
.Fc
.Sh DESCRIPTION
-These functions call the
-.Lb libc
-functions of the same names, passing through their return values when
-successful.
+These functions call the libc functions of the same names, passing
+through their return values when successful.
In case of failure, they do not return, but instead call
-.Xr perror 3
-and
-.Xr exit 3 .
-They can be used both internally by any code in the
-.Lb libmandoc
+.Xr err 3 .
+They can be used both internally by any code in the mandoc libraries
and externally by programs using that library, for example
.Xr mandoc 1 ,
+.Xr man 1 ,
.Xr apropos 1 ,
+.Xr makewhatis 8 ,
and
-.Xr makewhatis 8 .
+.Xr man.cgi 8 .
.Pp
The function
.Fn mandoc_malloc
@@ -149,9 +144,8 @@ These functions are implemented in
.Pa mandoc_aux.c .
.Sh SEE ALSO
.Xr asprintf 3 ,
-.Xr exit 3 ,
+.Xr err 3 ,
.Xr malloc 3 ,
-.Xr perror 3 ,
.Xr strdup 3
.Sh STANDARDS
The functions
diff --git a/contrib/mdocml/mandocdb.c b/contrib/mdocml/mandocdb.c
index 08f89c1..6c04cb0 100644
--- a/contrib/mdocml/mandocdb.c
+++ b/contrib/mdocml/mandocdb.c
@@ -1,4 +1,4 @@
-/* $Id: mandocdb.c,v 1.215 2016/01/08 17:48:09 schwarze Exp $ */
+/* $Id: mandocdb.c,v 1.218 2016/07/12 05:18:38 kristaps Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2016 Ingo Schwarze <schwarze@openbsd.org>
@@ -33,8 +33,10 @@
#else
#include "compat_fts.h"
#endif
-#include <getopt.h>
#include <limits.h>
+#if HAVE_SANDBOX_INIT
+#include <sandbox.h>
+#endif
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
@@ -346,6 +348,13 @@ mandocdb(int argc, char *argv[])
}
#endif
+#if HAVE_SANDBOX_INIT
+ if (sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, NULL) == -1) {
+ warnx("sandbox_init");
+ return (int)MANDOCLEVEL_SYSERR;
+ }
+#endif
+
memset(&conf, 0, sizeof(conf));
memset(stmts, 0, STMT__MAX * sizeof(sqlite3_stmt *));
@@ -574,7 +583,7 @@ usage:
* or
* [./]cat<section>[/<arch>]/<name>.0
*
- * TODO: accomodate for multi-language directories.
+ * TODO: accommodate for multi-language directories.
*/
static int
treescan(void)
diff --git a/contrib/mdocml/manpage.c b/contrib/mdocml/manpage.c
index 45b6e76..af7d3db 100644
--- a/contrib/mdocml/manpage.c
+++ b/contrib/mdocml/manpage.c
@@ -1,4 +1,4 @@
-/* $Id: manpage.c,v 1.13 2015/11/07 17:58:55 schwarze Exp $ */
+/* $Id: manpage.c,v 1.14 2016/07/09 15:24:19 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -20,7 +20,6 @@
#include <sys/types.h>
#include <assert.h>
-#include <getopt.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
diff --git a/contrib/mdocml/manpath.c b/contrib/mdocml/manpath.c
index 0627f13..83c329e 100644
--- a/contrib/mdocml/manpath.c
+++ b/contrib/mdocml/manpath.c
@@ -1,4 +1,4 @@
-/* $Id: manpath.c,v 1.29 2015/11/07 17:58:55 schwarze Exp $ */
+/* $Id: manpath.c,v 1.30 2016/05/28 13:44:13 schwarze Exp $ */
/*
* Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -224,13 +224,12 @@ manconf_file(struct manconf *conf, const char *file)
while ((linelen = getline(&line, &linesz, stream)) != -1) {
cp = line;
- ep = cp + linelen;
- if (ep[-1] != '\n')
- break;
- *--ep = '\0';
+ ep = cp + linelen - 1;
+ while (ep > cp && isspace((unsigned char)*ep))
+ *ep-- = '\0';
while (isspace((unsigned char)*cp))
cp++;
- if (*cp == '#')
+ if (cp == ep || *cp == '#')
continue;
for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) {
diff --git a/contrib/mdocml/mansearch.c b/contrib/mdocml/mansearch.c
index 843326b..1ab879d 100644
--- a/contrib/mdocml/mansearch.c
+++ b/contrib/mdocml/mansearch.c
@@ -1,4 +1,4 @@
-/* $Id: mansearch.c,v 1.64 2016/01/08 15:02:54 schwarze Exp $ */
+/* $Id: mansearch.c,v 1.65 2016/07/09 15:24:19 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -26,7 +26,6 @@
#endif
#include <errno.h>
#include <fcntl.h>
-#include <getopt.h>
#include <glob.h>
#include <limits.h>
#include <regex.h>
diff --git a/contrib/mdocml/mchars_alloc.3 b/contrib/mdocml/mchars_alloc.3
index 2d42a43..4bb8620 100644
--- a/contrib/mdocml/mchars_alloc.3
+++ b/contrib/mdocml/mchars_alloc.3
@@ -1,4 +1,4 @@
-.\" $Id: mchars_alloc.3,v 1.3 2015/10/13 22:59:54 schwarze Exp $
+.\" $Id: mchars_alloc.3,v 1.4 2016/07/07 19:19:01 schwarze Exp $
.\"
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: October 13 2015 $
+.Dd $Mdocdate: July 7 2016 $
.Dt MCHARS_ALLOC 3
.Os
.Sh NAME
@@ -23,7 +23,8 @@
.Nm mchars_num2char ,
.Nm mchars_num2uc ,
.Nm mchars_spec2cp ,
-.Nm mchars_spec2str
+.Nm mchars_spec2str ,
+.Nm mchars_uc2str
.Nd character table for mandoc
.Sh SYNOPSIS
.In sys/types.h
diff --git a/contrib/mdocml/read.c b/contrib/mdocml/read.c
index 0ef3cdf..6cbcd2d 100644
--- a/contrib/mdocml/read.c
+++ b/contrib/mdocml/read.c
@@ -1,4 +1,4 @@
-/* $Id: read.c,v 1.148 2016/01/08 02:53:13 schwarze Exp $ */
+/* $Id: read.c,v 1.149 2016/07/10 13:34:30 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
@@ -798,7 +798,7 @@ mparse_open(struct mparse *curp, const char *file)
if ( ! curp->gzip) {
mandoc_asprintf(&cp, "%s.gz", file);
- fd = open(file, O_RDONLY);
+ fd = open(cp, O_RDONLY);
free(cp);
if (fd != -1) {
curp->gzip = 1;
diff --git a/contrib/mdocml/tag.c b/contrib/mdocml/tag.c
index 57925ce..baedf15 100644
--- a/contrib/mdocml/tag.c
+++ b/contrib/mdocml/tag.c
@@ -1,4 +1,4 @@
-/* $Id: tag.c,v 1.11 2015/11/20 21:59:54 schwarze Exp $ */
+/* $Id: tag.c,v 1.12 2016/07/08 20:42:15 schwarze Exp $ */
/*
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -57,6 +57,24 @@ tag_init(void)
tag_files.tfd = -1;
tag_files.tcpgid = -1;
+ /* Clean up when dying from a signal. */
+
+ memset(&sa, 0, sizeof(sa));
+ sigfillset(&sa.sa_mask);
+ sa.sa_handler = tag_signal;
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+ /*
+ * POSIX requires that a process calling tcsetpgrp(3)
+ * from the background gets a SIGTTOU signal.
+ * In that case, do not stop.
+ */
+
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGTTOU, &sa, NULL);
+
/* Save the original standard output for use by the pager. */
if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1)
@@ -68,12 +86,6 @@ tag_init(void)
sizeof(tag_files.ofn));
(void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX",
sizeof(tag_files.tfn));
- memset(&sa, 0, sizeof(sa));
- sigfillset(&sa.sa_mask);
- sa.sa_handler = tag_signal;
- sigaction(SIGHUP, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
if ((ofd = mkstemp(tag_files.ofn)) == -1)
goto fail;
if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1)
diff --git a/contrib/mdocml/term.c b/contrib/mdocml/term.c
index e917101..0fd8f7c 100644
--- a/contrib/mdocml/term.c
+++ b/contrib/mdocml/term.c
@@ -1,4 +1,4 @@
-/* $Id: term.c,v 1.256 2016/01/07 21:03:54 schwarze Exp $ */
+/* $Id: term.c,v 1.257 2016/04/12 15:30:00 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -160,7 +160,7 @@ term_flushln(struct termp *p)
if (' ' == p->buf[j] || '\t' == p->buf[j])
break;
- /* Back over the the last printed character. */
+ /* Back over the last printed character. */
if (8 == p->buf[j]) {
assert(j);
vend -= (*p->width)(p, p->buf[j - 1]);
diff --git a/contrib/mdocml/term_ascii.c b/contrib/mdocml/term_ascii.c
index 7215a59..fecdb0a 100644
--- a/contrib/mdocml/term_ascii.c
+++ b/contrib/mdocml/term_ascii.c
@@ -1,4 +1,4 @@
-/* $Id: term_ascii.c,v 1.52 2015/11/12 21:50:03 schwarze Exp $ */
+/* $Id: term_ascii.c,v 1.53 2016/07/08 22:29:05 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -163,18 +163,17 @@ ascii_setwidth(struct termp *p, int iop, int width)
}
void
-ascii_sepline(void *arg)
+terminal_sepline(void *arg)
{
struct termp *p;
size_t i;
p = (struct termp *)arg;
- p->line += 3;
- putchar('\n');
+ (*p->endline)(p);
for (i = 0; i < p->defrmargin; i++)
- putchar('-');
- putchar('\n');
- putchar('\n');
+ (*p->letter)(p, '-');
+ (*p->endline)(p);
+ (*p->endline)(p);
}
static size_t
diff --git a/contrib/mdocml/test-rewb-bsd.c b/contrib/mdocml/test-rewb-bsd.c
index 88d3d35..872dd4c 100644
--- a/contrib/mdocml/test-rewb-bsd.c
+++ b/contrib/mdocml/test-rewb-bsd.c
@@ -1,4 +1,5 @@
#include <sys/types.h>
+#include <stddef.h>
#include <regex.h>
int
diff --git a/contrib/mdocml/test-rewb-sysv.c b/contrib/mdocml/test-rewb-sysv.c
index cb35c54..1e7fbc8 100644
--- a/contrib/mdocml/test-rewb-sysv.c
+++ b/contrib/mdocml/test-rewb-sysv.c
@@ -1,4 +1,5 @@
#include <sys/types.h>
+#include <stddef.h>
#include <regex.h>
int
diff --git a/contrib/top/commands.c b/contrib/top/commands.c
index 53a45ee..7114fcf 100644
--- a/contrib/top/commands.c
+++ b/contrib/top/commands.c
@@ -104,6 +104,7 @@ S - toggle the displaying of system processes\n\
a - toggle the displaying of process titles\n\
t - toggle the display of this process\n\
u - display processes for only one user (+ selects all users)\n\
+w - toggle the display of swap use for each process\n\
z - toggle the displaying of the system idle process\n\
\n\
\n", stdout);
diff --git a/contrib/top/machine.h b/contrib/top/machine.h
index 3aad758..6f2844d 100644
--- a/contrib/top/machine.h
+++ b/contrib/top/machine.h
@@ -72,6 +72,7 @@ struct process_select
int wcpu; /* show weighted cpu */
int jid; /* only this jid (unless jid == -1) */
int jail; /* show jail ID */
+ int swap; /* show swap usage */
int kidle; /* show per-CPU idle threads */
char *command; /* only this command (unless == NULL) */
};
@@ -82,8 +83,8 @@ char *format_header();
char *format_next_process();
void toggle_pcpustats(void);
void get_system_info(struct system_info *si);
-int machine_init(struct statics *statics, char do_unames);
-int proc_owner(int pid);
+int machine_init(struct statics *statics, char do_unames);
+int proc_owner(int pid);
/* non-int routines typically used by the machine dependent module */
char *printable();
diff --git a/contrib/top/top.c b/contrib/top/top.c
index 64c3d5f..c74c1d1 100644
--- a/contrib/top/top.c
+++ b/contrib/top/top.c
@@ -188,9 +188,9 @@ char *argv[];
fd_set readfds;
#ifdef ORDER
- static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJo";
+ static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwo";
#else
- static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJ";
+ static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJw";
#endif
/* these defines enumerate the "strchr"s of the commands in command_chars */
#define CMD_redraw 0
@@ -219,8 +219,9 @@ char *argv[];
#define CMD_kidletog 22
#define CMD_pcputog 23
#define CMD_jail 24
+#define CMD_swaptog 25
#ifdef ORDER
-#define CMD_order 25
+#define CMD_order 26
#endif
/* set the buffer for stdout */
@@ -254,6 +255,7 @@ char *argv[];
ps.wcpu = 1;
ps.jid = -1;
ps.jail = No;
+ ps.swap = No;
ps.kidle = Yes;
ps.command = NULL;
@@ -280,7 +282,7 @@ char *argv[];
optind = 1;
}
- while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:t")) != EOF)
+ while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:tw")) != EOF)
{
switch(i)
{
@@ -418,6 +420,10 @@ char *argv[];
pcpu_stats = !pcpu_stats;
break;
+ case 'w':
+ ps.swap = 1;
+ break;
+
case 'z':
ps.kidle = !ps.kidle;
break;
@@ -1141,6 +1147,15 @@ restart:
reset_display();
putchar('\r');
break;
+ case CMD_swaptog:
+ ps.swap = !ps.swap;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying per-process swap usage.",
+ ps.swap ? "D" : "Not d");
+ header_text = format_header(uname_field);
+ reset_display();
+ putchar('\r');
+ break;
default:
new_message(MT_standout, " BAD CASE IN SWITCH!");
putchar('\r');
diff --git a/contrib/top/top.xs b/contrib/top/top.xs
index 15cf2dc..d3829f3 100644
--- a/contrib/top/top.xs
+++ b/contrib/top/top.xs
@@ -10,7 +10,7 @@ top \- display and update information about the top cpu processes
.SH SYNOPSIS
.B top
[
-.B \-abCHIijnPqStuvz
+.B \-abCHIijnPqStuvwz
] [
.BI \-d count
] [
@@ -148,6 +148,9 @@ Write version number information to stderr then exit immediately.
No other processing takes place when this option is used. To see current
revision information while top is running, use the help command \*(lq?\*(rq.
.TP
+.B \-w
+Display approximate swap usage for each process.
+.TP
.B \-z
Do not display the system idle process.
.TP
@@ -167,11 +170,12 @@ Set the delay between screen updates to
seconds. The default delay between updates is \nD seconds.
.TP
.BI \-o field
-Sort the process display area on the specified field. The field name is
-the name of the column as seen in the output, but in lower case. Likely
-values are \*(lqcpu\*(rq, \*(lqsize\*(rq, \*(lqres\*(rq, and \*(lqtime\*(rq,
-but may vary on different operating systems. Note that
-not all operating systems support this option.
+Sort the process display area on the specified field. The field name
+is the name of the column as seen in the output, but in lower case:
+\*(lqcpu\*(lq, \*(rqsize\*(lq, \*(rqres\*(lq, \*(rqtime\*(lq,
+\*(rqpri\*(lq, \*(rqthreads\*(lq, \*(lqtotal\*(lq, \*(rqread\*(lq,
+\*(rqwrite\*(lq, \*(rqfault\*(lq, \*(rqvcsw\*(lq, \*(rqivcsw\*(lq,
+\*(lqjid\*(lq, \*(rqswap\*(lq or \*(rqpid\*(lq.
.TP
.BI \-J jail
Show only those processes owned by
@@ -226,6 +230,7 @@ The options
.BR \-S ,
.BR \-t ,
.BR \-u ,
+.BR \-w ,
and
.B \-z
are actually toggles. A second specification of any of these options
@@ -346,6 +351,9 @@ Toggle the display of the
.I top
process.
.TP
+.B w
+Toggle the display of swap usage.
+.TP
.B z
Toggle the display of the system idle process.
.SH "THE DISPLAY"
@@ -379,8 +387,9 @@ is specified, a UID column will be substituted for USERNAME),
PRI is the current priority of the process,
NICE is the nice amount (in the range \-20 to 20),
SIZE is the total size of the process (text, data, and stack),
-RES is the current amount of resident memory (both SIZE and RES are
-given in kilobytes),
+RES is the current amount of resident memory,
+SWAP is the approximate amount of swap, if enabled
+(SIZE, RES and SWAP are given in kilobytes),
STATE is the current state (one of \*(lqSTART\*(rq, \*(lqRUN\*(rq
(shown as \*(lqCPUn\*(rq on SMP systems), \*(lqSLEEP\*(rq, \*(lqSTOP\*(rq,
\*(lqZOMB\*(rq, \*(lqWAIT\*(rq, \*(lqLOCK\*(rq or the event on which the
diff --git a/contrib/tzdata/asia b/contrib/tzdata/asia
index 71ef878..b2c9930 100644
--- a/contrib/tzdata/asia
+++ b/contrib/tzdata/asia
@@ -2544,11 +2544,6 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# From Paul Eggert (2015-03-03):
# http://www.timeanddate.com/time/change/west-bank/ramallah?year=2014
# says that the fall 2014 transition was Oct 23 at 24:00.
-# For future dates, guess the last Friday in March at 24:00 through
-# the first Friday on or after October 21 at 00:00. This is consistent with
-# the predictions in today's editions of the following URLs:
-# http://www.timeanddate.com/time/change/gaza-strip/gaza
-# http://www.timeanddate.com/time/change/west-bank/hebron
# From Hannah Kreitem (2016-03-09):
# http://www.palestinecabinet.gov.ps/WebSite/ar/ViewDetails?ID=31728
@@ -2558,7 +2553,21 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
#
# From Paul Eggert (2016-03-12):
# Predict spring transitions on March's last Saturday at 01:00 from now on.
-# Leave fall predictions alone for now.
+
+# From Sharef Mustafa (2016-10-19):
+# [T]he Palestinian cabinet decision (Mar 8th 2016) published on
+# http://www.palestinecabinet.gov.ps/WebSite/Upload/Decree/GOV_17/16032016134830.pdf
+# states that summer time will end on Oct 29th at 01:00.
+#
+# From Tim Parenti (2016-10-19):
+# Predict fall transitions on October's last Saturday at 01:00 from now on.
+# This is consistent with the 2016 transition as well as our spring
+# predictions.
+#
+# From Paul Eggert (2016-10-19):
+# It's also consistent with predictions in the following URLs today:
+# http://www.timeanddate.com/time/change/gaza-strip/gaza
+# http://www.timeanddate.com/time/change/west-bank/hebron
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule EgyptAsia 1957 only - May 10 0:00 1:00 S
@@ -2587,9 +2596,10 @@ Rule Palestine 2011 only - Sep 30 0:00 0 -
Rule Palestine 2012 2014 - Mar lastThu 24:00 1:00 S
Rule Palestine 2012 only - Sep 21 1:00 0 -
Rule Palestine 2013 only - Sep Fri>=21 0:00 0 -
-Rule Palestine 2014 max - Oct Fri>=21 0:00 0 -
+Rule Palestine 2014 2015 - Oct Fri>=21 0:00 0 -
Rule Palestine 2015 only - Mar lastFri 24:00 1:00 S
Rule Palestine 2016 max - Mar lastSat 1:00 1:00 S
+Rule Palestine 2016 max - Oct lastSat 1:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
@@ -2739,45 +2749,31 @@ Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1
# People who live in regions under Tamil control can use [TZ='Asia/Kolkata'],
# as that zone has agreed with the Tamil areas since our cutoff date of 1970.
-# From K Sethu (2006-04-25):
-# I think the abbreviation LKT originated from the world of computers at
-# the time of or subsequent to the time zone changes by SL Government
-# twice in 1996 and probably SL Government or its standardization
-# agencies never declared an abbreviation as a national standard.
-#
-# I recollect before the recent change the government announcements
-# mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
-# Time and no mention was made about the abbreviation.
-#
-# If we look at Sri Lanka Department of Government's "Official News
-# Website of Sri Lanka" ... http://www.news.lk/ we can see that they
-# use SLT as abbreviation in time stamp at the beginning of each news
-# item....
-#
-# Within Sri Lanka I think LKT is well known among computer users and
-# administrators. In my opinion SLT may not be a good choice because the
-# nation's largest telcom / internet operator Sri Lanka Telcom is well
-# known by that abbreviation - simply as SLT (there IP domains are
-# slt.lk and sltnet.lk).
-#
-# But if indeed our government has adopted SLT as standard abbreviation
-# (that we have not known so far) then it is better that it be used for
-# all computers.
-
-# From Paul Eggert (2006-04-25):
-# One possibility is that we wait for a bit for the dust to settle down
-# and then see what people actually say in practice.
+# From Sadika Sumanapala (2016-10-19):
+# According to http://www.sltime.org (maintained by Measurement Units,
+# Standards & Services Department, Sri Lanka) abbreviation for Sri Lanka
+# standard time is SLST.
+#
+# From Paul Eggert (2016-10-18):
+# "SLST" seems to be reasonably recent and rarely-used outside time
+# zone nerd sources. I searched Google News and found three uses of
+# it in the International Business Times of India in February and
+# March of this year when discussing cricket match times, but nothing
+# since then (though there has been a lot of cricket) and nothing in
+# other English-language news sources. Our old abbreviation "LKT" is
+# even worse. For now, let's use a numeric abbreviation; we can
+# switch to "SLST" if it catches on.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Colombo 5:19:24 - LMT 1880
5:19:32 - MMT 1906 # Moratuwa Mean Time
- 5:30 - IST 1942 Jan 5
- 5:30 0:30 IHST 1942 Sep
- 5:30 1:00 IST 1945 Oct 16 2:00
- 5:30 - IST 1996 May 25 0:00
- 6:30 - LKT 1996 Oct 26 0:30
- 6:00 - LKT 2006 Apr 15 0:30
- 5:30 - IST
+ 5:30 - +0530 1942 Jan 5
+ 5:30 0:30 +0530/+06 1942 Sep
+ 5:30 1:00 +0530/+0630 1945 Oct 16 2:00
+ 5:30 - +0530 1996 May 25 0:00
+ 6:30 - +0630 1996 Oct 26 0:30
+ 6:00 - +06 2006 Apr 15 0:30
+ 5:30 - +0530
# Syria
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
diff --git a/contrib/tzdata/australasia b/contrib/tzdata/australasia
index f49df1d..85d3632 100644
--- a/contrib/tzdata/australasia
+++ b/contrib/tzdata/australasia
@@ -350,7 +350,13 @@ Zone Indian/Cocos 6:27:40 - LMT 1900
# commencing at 2.00 am on Sunday 1st November, 2015 and ending at
# 3.00 am on Sunday 17th January, 2016.
-# From Paul Eggert (2015-09-01):
+# From Raymond Kumar (2016-10-04):
+# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVING-STARTS-ON-6th-NOVEMBER,-2016.aspx
+# "Fiji's daylight savings will begin on Sunday, 6 November 2016, when
+# clocks go forward an hour at 2am to 3am.... Daylight Saving will
+# end at 3.00am on Sunday 15th January 2017."
+
+# From Paul Eggert (2016-10-03):
# For now, guess DST from 02:00 the first Sunday in November to
# 03:00 the third Sunday in January. Although ad hoc, it matches
# transitions since late 2014 and seems more likely to match future
diff --git a/contrib/tzdata/europe b/contrib/tzdata/europe
index 6020059..a7dc350 100644
--- a/contrib/tzdata/europe
+++ b/contrib/tzdata/europe
@@ -1908,7 +1908,7 @@ Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
# Amsterdam mean time.
# The data entries before 1945 are taken from
-# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
+# http://www.staff.science.uu.nl/~gent0113/idl/idl.htm
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Neth 1916 only - May 1 0:00 1:00 NST # Netherlands Summer Time
@@ -3427,22 +3427,24 @@ Zone Europe/Zurich 0:34:08 - LMT 1853 Jul 16 # See above comment.
# Turkey
-# From Amar Devegowda (2007-01-03):
-# The time zone rules for Istanbul, Turkey have not been changed for years now.
-# ... The latest rules are available at:
-# http://www.timeanddate.com/worldclock/timezone.html?n=107
-# From Steffen Thorsen (2007-01-03):
-# I have been able to find press records back to 1996 which all say that
-# DST started 01:00 local time and end at 02:00 local time. I am not sure
-# what happened before that. One example for each year from 1996 to 2001:
-# http://newspot.byegm.gov.tr/arsiv/1996/21/N4.htm
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING97/03/97X03X25.TXT
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING98/03/98X03X02.HTM
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING99/10/99X10X26.HTM#%2016
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2000/03/00X03X06.HTM#%2021
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2001/03/23x03x01.HTM#%2027
-# From Paul Eggert (2007-01-03):
-# Prefer the above source to Shanks & Pottenger for time stamps after 1990.
+# From Kıvanç Yazan (2016-09-25):
+# 1) For 1986-2006, DST started at 01:00 local and ended at 02:00 local, with
+# no exceptions.
+# 2) 1994's lastSun was overridden with Mar 20 ...
+# Here are official papers:
+# http://www.resmigazete.gov.tr/arsiv/19032.pdf - page 2 for 1986
+# http://www.resmigazete.gov.tr/arsiv/19400.pdf - page 4 for 1987
+# http://www.resmigazete.gov.tr/arsiv/19752.pdf - page 15 for 1988
+# http://www.resmigazete.gov.tr/arsiv/20102.pdf - page 6 for 1989
+# http://www.resmigazete.gov.tr/arsiv/20464.pdf - page 1 for 1990 - 1992
+# http://www.resmigazete.gov.tr/arsiv/21531.pdf - page 15 for 1993 - 1995
+# http://www.resmigazete.gov.tr/arsiv/21879.pdf - page 1 for overriding 1994
+# http://www.resmigazete.gov.tr/arsiv/22588.pdf - page 1 for 1996, 1997
+# http://www.resmigazete.gov.tr/arsiv/23286.pdf - page 10 for 1998 - 2000
+# http://www.resmigazete.gov.tr/eskiler/2001/03/20010324.htm#2 - for 2001
+# http://www.resmigazete.gov.tr/eskiler/2002/03/20020316.htm#2 - for 2002-2006
+# From Paul Eggert (2016-09-25):
+# Prefer the above sources to Shanks & Pottenger for time stamps after 1985.
# From Steffen Thorsen (2007-03-09):
# Starting 2007 though, it seems that they are adopting EU's 1:00 UTC
@@ -3551,10 +3553,10 @@ Rule Turkey 1983 only - Jul 31 0:00 1:00 S
Rule Turkey 1983 only - Oct 2 0:00 0 -
Rule Turkey 1985 only - Apr 20 0:00 1:00 S
Rule Turkey 1985 only - Sep 28 0:00 0 -
-Rule Turkey 1986 1990 - Mar lastSun 2:00s 1:00 S
-Rule Turkey 1986 1990 - Sep lastSun 2:00s 0 -
-Rule Turkey 1991 2006 - Mar lastSun 1:00s 1:00 S
-Rule Turkey 1991 1995 - Sep lastSun 1:00s 0 -
+Rule Turkey 1986 1993 - Mar lastSun 1:00s 1:00 S
+Rule Turkey 1986 1995 - Sep lastSun 1:00s 0 -
+Rule Turkey 1994 only - Mar 20 1:00s 1:00 S
+Rule Turkey 1995 2006 - Mar lastSun 1:00s 1:00 S
Rule Turkey 1996 2006 - Oct lastSun 1:00s 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Istanbul 1:55:52 - LMT 1880
diff --git a/contrib/tzdata/northamerica b/contrib/tzdata/northamerica
index 0bafb00..e1ed9e4 100644
--- a/contrib/tzdata/northamerica
+++ b/contrib/tzdata/northamerica
@@ -24,8 +24,32 @@
# was the result of his proposals at the Convention of Railroad Trunk Lines
# in New York City (1869-10). His 1870 proposal was based on Washington, DC,
# but in 1872-05 he moved the proposed origin to Greenwich.
-# His proposal was adopted by the railroads on 1883-11-18 at 12:00,
-# and the most of the country soon followed suit.
+
+# From Paul Eggert (2016-09-21):
+# Dowd's proposal left many details unresolved, such as where to draw
+# lines between time zones. The key individual who made time zones
+# work in the US was William Frederick Allen - railway engineer,
+# managing editor of the Travelers' Guide, and secretary of the
+# General Time Convention, a railway standardization group. Allen
+# spent months in dialogs with scientific and railway leaders,
+# developed a workable plan to institute time zones, and presented it
+# to the General Time Convention on 1883-04-11, saying that his plan
+# meant "local time would be practically abolished" - a plus for
+# railway scheduling. By the next convention on 1883-10-11 nearly all
+# railroads had agreed and it took effect on 1883-11-18 at 12:00.
+# That Sunday was called the "day of two noons", as the eastern parts
+# of the new zones observed noon twice. Allen witnessed the
+# transition in New York City, writing:
+#
+# I heard the bells of St. Paul's strike on the old time. Four
+# minutes later, obedient to the electrical signal from the Naval
+# Observatory ... the time-ball made its rapid descent, the chimes
+# of old Trinity rang twelve measured strokes, and local time was
+# abandoned, probably forever.
+#
+# Most of the US soon followed suit. See:
+# Bartky IR. The adoption of standard time. Technol Cult 1989 Jan;30(1):25-56.
+# http://dx.doi.org/10.2307/3105430
# From Paul Eggert (2005-04-16):
# That 1883 transition occurred at 12:00 new time, not at 12:00 old time.
diff --git a/contrib/unbound/Makefile.in b/contrib/unbound/Makefile.in
index ff46581..77e38ea 100644
--- a/contrib/unbound/Makefile.in
+++ b/contrib/unbound/Makefile.in
@@ -81,7 +81,7 @@ LINTFLAGS+=@NETBSD_LINTFLAGS@
# compat with OpenBSD
LINTFLAGS+="-Dsigset_t=long"
# FreeBSD
-LINTFLAGS+="-D__uint16_t=uint16_t" "-DEVP_PKEY_ASN1_METHOD=int" "-D_RuneLocale=int" "-D__va_list=va_list"
+LINTFLAGS+="-D__uint16_t=uint16_t" "-DEVP_PKEY_ASN1_METHOD=int" "-D_RuneLocale=int" "-D__va_list=va_list" "-D__uint32_t=uint32_t"
INSTALL=$(SHELL) $(srcdir)/install-sh
@@ -108,11 +108,12 @@ util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
util/rtt.c util/storage/dnstree.c util/storage/lookup3.c \
util/storage/lruhash.c util/storage/slabhash.c util/timehist.c util/tube.c \
-util/winsock_event.c validator/autotrust.c validator/val_anchor.c \
-validator/validator.c validator/val_kcache.c validator/val_kentry.c \
-validator/val_neg.c validator/val_nsec3.c validator/val_nsec.c \
-validator/val_secalgo.c validator/val_sigcrypt.c \
-validator/val_utils.c dns64/dns64.c $(CHECKLOCK_SRC) $(DNSTAP_SRC)
+util/ub_event.c util/ub_event_pluggable.c util/winsock_event.c \
+validator/autotrust.c validator/val_anchor.c validator/validator.c \
+validator/val_kcache.c validator/val_kentry.c validator/val_neg.c \
+validator/val_nsec3.c validator/val_nsec.c validator/val_secalgo.c \
+validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c cachedb/cachedb.c $(CHECKLOCK_SRC) \
+$(DNSTAP_SRC)
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
@@ -122,10 +123,11 @@ fptr_wlist.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
slabhash.lo timehist.lo tube.lo winsock_event.lo autotrust.lo val_anchor.lo \
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
-val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo \
+val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo \
$(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ)
-COMMON_OBJ=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
+COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
outside_network.lo
+COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
# set to $COMMON_OBJ or to "" if --enableallsymbols
COMMON_OBJ_ALL_SYMBOLS=@COMMON_OBJ_ALL_SYMBOLS@
COMPAT_SRC=compat/ctime_r.c compat/fake-rfc2553.c compat/gmtime_r.c \
@@ -134,7 +136,8 @@ compat/memcmp.c compat/memmove.c compat/snprintf.c compat/strlcat.c \
compat/strlcpy.c compat/strptime.c compat/getentropy_linux.c \
compat/getentropy_osx.c compat/getentropy_solaris.c compat/getentropy_win.c \
compat/explicit_bzero.c compat/arc4random.c compat/arc4random_uniform.c \
-compat/arc4_lock.c compat/sha512.c compat/reallocarray.c compat/isblank.c
+compat/arc4_lock.c compat/sha512.c compat/reallocarray.c compat/isblank.c \
+compat/strsep.c
COMPAT_OBJ=$(LIBOBJS:.o=.lo)
COMPAT_OBJ_WITHOUT_CTIME=$(LIBOBJ_WITHOUT_CTIME:.o=.lo)
COMPAT_OBJ_WITHOUT_CTIMEARC4=$(LIBOBJ_WITHOUT_CTIMEARC4:.o=.lo)
@@ -177,7 +180,8 @@ daemon/worker.c daemon/acl_list.c daemon/daemon.c daemon/stats.c \
testcode/replay.c testcode/fake_event.c
TESTBOUND_OBJ=testbound.lo replay.lo fake_event.lo
TESTBOUND_OBJ_LINK=$(TESTBOUND_OBJ) testpkts.lo worker.lo acl_list.lo \
-daemon.lo stats.lo $(COMMON_OBJ_WITHOUT_NETCALL) $(SLDNS_OBJ) $(COMPAT_OBJ)
+daemon.lo stats.lo $(COMMON_OBJ_WITHOUT_NETCALL) ub_event.lo $(SLDNS_OBJ) \
+$(COMPAT_OBJ)
LOCKVERIFY_SRC=testcode/lock_verify.c
LOCKVERIFY_OBJ=lock_verify.lo
LOCKVERIFY_OBJ_LINK=$(LOCKVERIFY_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \
@@ -209,8 +213,8 @@ DELAYER_OBJ_LINK=$(DELAYER_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \
$(SLDNS_OBJ)
LIBUNBOUND_SRC=libunbound/context.c libunbound/libunbound.c \
libunbound/libworker.c
-LIBUNBOUND_OBJ=context.lo libunbound.lo libworker.lo
-LIBUNBOUND_OBJ_LINK=$(LIBUNBOUND_OBJ) $(COMMON_OBJ) $(SLDNS_OBJ) $(COMPAT_OBJ)
+LIBUNBOUND_OBJ=context.lo libunbound.lo libworker.lo ub_event_pluggable.lo
+LIBUNBOUND_OBJ_LINK=$(LIBUNBOUND_OBJ) $(COMMON_OBJ_WITHOUT_UB_EVENT) $(SLDNS_OBJ) $(COMPAT_OBJ)
# win apps or "" if not on windows
WINAPPS=@WINAPPS@
@@ -224,7 +228,7 @@ SVCUNINST_OBJ_LINK=$(SVCUNINST_OBJ) w_inst.lo rsrc_svcuninst.o \
$(COMPAT_OBJ_WITHOUT_CTIMEARC4)
ANCHORUPD_SRC=winrc/anchor-update.c
ANCHORUPD_OBJ=anchor-update.lo
-ANCHORUPD_OBJ_LINK=$(ANCHORUPD_OBJ) rsrc_anchorupd.o $(COMPAT_OBJ_WITHOUT_CTIMEARC4)
+ANCHORUPD_OBJ_LINK=$(ANCHORUPD_OBJ) rsrc_anchorupd.o $(COMPAT_OBJ_WITHOUT_CTIMEARC4) wire2str.lo str2wire.lo parseutil.lo sbuffer.lo rrdef.lo keyraw.lo parse.lo
RSRC_OBJ=rsrc_svcinst.o rsrc_svcuninst.o rsrc_anchorupd.o rsrc_unbound.o \
rsrc_unbound_host.o rsrc_unbound_anchor.o rsrc_unbound_control.o \
rsrc_unbound_checkconf.o
@@ -552,7 +556,7 @@ uninstall: $(PYTHONMOD_UNINSTALL) $(PYUNBOUND_UNINSTALL) $(UNBOUND_EVENT_UNINSTA
@echo "You still need to remove "`dirname $(DESTDIR)$(configfile)`" , $(DESTDIR)$(configfile) by hand"
iana_update:
- curl -o port-numbers.tmp http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml --compressed
+ curl -o port-numbers.tmp https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml --compressed
if file port-numbers.tmp | grep 'gzip' >/dev/null; then zcat port-numbers.tmp; else cat port-numbers.tmp; fi | awk '/<record>/ {p=0;} /<protocol>udp/ {p=1;} /<protocol>[^u]/ {p=0;} /Decomissioned|Decommissioned|Removed|De-registered|unassigned|Unassigned|Reserved/ {u=1;} /<number>/ { if(u==1) {u=0;} else { if(p==1) { match($$0,/[0-9]+/); print substr($$0, RSTART, RLENGTH) ","}}}' | sort -nu > util/iana_ports.inc
rm -f port-numbers.tmp
@@ -596,7 +600,6 @@ depend:
rm -f $(DEPEND_TMP) $(DEPEND_TMP2)
# Dependencies
-as112.lo as112.o: $(srcdir)/util/as112.c $(srcdir)/util/as112.h
dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
$(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/msgreply.h \
@@ -614,6 +617,7 @@ rrset.lo rrset.o: $(srcdir)/services/cache/rrset.c config.h $(srcdir)/services/c
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/slabhash.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/config_file.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/regional.h $(srcdir)/util/alloc.h
+as112.lo as112.o: $(srcdir)/util/as112.c $(srcdir)/util/as112.h
dname.lo dname.o: $(srcdir)/util/data/dname.c config.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/storage/lookup3.h $(srcdir)/sldns/sbuffer.h
@@ -624,9 +628,9 @@ msgencode.lo msgencode.o: $(srcdir)/util/data/msgencode.c config.h $(srcdir)/uti
$(srcdir)/sldns/sbuffer.h
msgparse.lo msgparse.o: $(srcdir)/util/data/msgparse.c config.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/dname.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h \
- $(srcdir)/sldns/wire2str.h
+ $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/netevent.h $(srcdir)/util/net_help.h \
@@ -700,11 +704,12 @@ listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h
$(srcdir)/util/rbtree.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h \
$(srcdir)/util/net_help.h $(srcdir)/sldns/sbuffer.h
localzone.lo localzone.o: $(srcdir)/services/localzone.c config.h $(srcdir)/services/localzone.h \
- $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/netevent.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/util/as112.h
+ $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/regional.h \
+ $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/netevent.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/util/as112.h
mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/netevent.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
@@ -718,7 +723,7 @@ modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/service
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/dns64/dns64.h \
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h \
- $(srcdir)/validator/val_utils.h
+ $(srcdir)/validator/val_utils.h $(PYTHONMOD_HEADER) $(srcdir)/cachedb/cachedb.h
outbound_list.lo outbound_list.o: $(srcdir)/services/outbound_list.c config.h \
$(srcdir)/services/outbound_list.h $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/netevent.h
@@ -755,14 +760,15 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/mini_event.h \
$(srcdir)/util/rbtree.h $(srcdir)/services/outside_network.h \
- $(srcdir)/services/localzone.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/infra.h \
$(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h \
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h \
$(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
$(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h
+ $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h \
+ $(PYTHONMOD_HEADER) $(srcdir)/cachedb/cachedb.h
locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
@@ -773,12 +779,12 @@ mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/
module.lo module.o: $(srcdir)/util/module.c config.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h
-netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/netevent.h $(srcdir)/util/log.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
+netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/netevent.h $(srcdir)/util/ub_event.h \
+ $(srcdir)/util/log.h $(srcdir)/util/net_help.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/locks.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/dnstap/dnstap.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
+ $(srcdir)/dnstap/dnstap.h
net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
@@ -808,7 +814,15 @@ tube.lo tube.o: $(srcdir)/util/tube.c config.h $(srcdir)/util/tube.h $(srcdir)/u
$(srcdir)/util/netevent.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/mesh.h \
- $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
+ $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/ub_event.h
+ub_event.lo ub_event.o: $(srcdir)/util/ub_event.c config.h $(srcdir)/util/ub_event.h $(srcdir)/util/log.h \
+ $(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
+ub_event_pluggable.lo ub_event_pluggable.o: $(srcdir)/util/ub_event_pluggable.c config.h $(srcdir)/util/ub_event.h \
+ $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/netevent.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/modstack.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
winsock_event.lo winsock_event.o: $(srcdir)/util/winsock_event.c config.h
autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/validator/autotrust.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
@@ -822,8 +836,8 @@ autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/val
val_anchor.lo val_anchor.o: $(srcdir)/validator/val_anchor.c config.h $(srcdir)/validator/val_anchor.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_sigcrypt.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/validator/autotrust.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h $(srcdir)/util/as112.h
+ $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/util/as112.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
validator.lo validator.o: $(srcdir)/validator/validator.c config.h $(srcdir)/validator/validator.h \
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
@@ -880,7 +894,7 @@ val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/val
$(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h \
$(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_neg.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/regional.h
+ $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h
dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.h $(srcdir)/util/module.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
@@ -888,6 +902,14 @@ dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.h $(src
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/config_file.h $(srcdir)/util/fptr_wlist.h \
$(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
$(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h
+cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.h $(srcdir)/cachedb/cachedb.h $(srcdir)/util/module.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/data/msgencode.h $(srcdir)/services/cache/dns.h $(srcdir)/validator/val_neg.h \
+ $(srcdir)/util/rbtree.h $(srcdir)/validator/val_secalgo.h $(srcdir)/iterator/iter_utils.h \
+ $(srcdir)/iterator/iter_resptype.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h \
+ $(srcdir)/sldns/sbuffer.h
checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/testcode/checklocks.h
unitanchor.lo unitanchor.o: $(srcdir)/testcode/unitanchor.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
@@ -935,7 +957,8 @@ unitldns.lo unitldns.o: $(srcdir)/testcode/unitldns.c config.h $(srcdir)/util/lo
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/regional.h $(srcdir)/util/log.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h
+ $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h $(srcdir)/util/locks.h \
+ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h $(srcdir)/daemon/cachedump.h \
$(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
@@ -994,7 +1017,7 @@ unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h $
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/fptr_wlist.h \
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
+ $(srcdir)/util/ub_event.h
worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
$(srcdir)/util/random.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
@@ -1020,7 +1043,7 @@ testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/test
$(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/util/rtt.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
+ $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcode/testpkts.h \
$(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
@@ -1042,7 +1065,8 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
$(srcdir)/libunbound/libworker.h
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/regional.h $(srcdir)/util/log.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h
+ $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h $(srcdir)/util/locks.h \
+ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
@@ -1101,7 +1125,7 @@ unbound-checkconf.lo unbound-checkconf.o: $(srcdir)/smallapp/unbound-checkconf.c
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
$(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/services/localzone.h \
- $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/sldns/sbuffer.h $(PYTHONMOD_HEADER)
worker_cb.lo worker_cb.o: $(srcdir)/smallapp/worker_cb.c config.h $(srcdir)/libunbound/context.h \
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
$(srcdir)/libunbound/unbound.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
@@ -1113,17 +1137,18 @@ context.lo context.o: $(srcdir)/libunbound/context.c config.h $(srcdir)/libunbou
$(srcdir)/libunbound/unbound.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/sldns/sbuffer.h
libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \
$(srcdir)/libunbound/unbound-event.h config.h $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/libunbound/libworker.h \
$(srcdir)/util/config_file.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h \
- $(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/services/localzone.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/util/ub_event.h \
+ $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/infra.h \
+ $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
+ $(srcdir)/sldns/sbuffer.h
libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/libunbound/libworker.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
@@ -1131,11 +1156,12 @@ libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/li
$(srcdir)/libunbound/unbound-event.h $(srcdir)/services/outside_network.h $(srcdir)/util/netevent.h \
$(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/services/localzone.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h \
- $(srcdir)/util/random.h $(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h \
- $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/str2wire.h
+ $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h $(srcdir)/util/fptr_wlist.h \
+ $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
+ $(srcdir)/sldns/str2wire.h
unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libunbound/unbound.h \
@@ -1163,14 +1189,15 @@ pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.c conf
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/util/netevent.h $(srcdir)/util/net_help.h $(srcdir)/services/cache/dns.h \
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/regional.h \
- $(srcdir)/iterator/iter_delegpt.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/iterator/iter_delegpt.h $(srcdir)/sldns/sbuffer.h \
+
win_svc.lo win_svc.o: $(srcdir)/winrc/win_svc.c config.h $(srcdir)/winrc/win_svc.h $(srcdir)/winrc/w_inst.h \
$(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/netevent.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/util/module.h \
- $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/winsock_event.h
+ $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/ub_event.h
w_inst.lo w_inst.o: $(srcdir)/winrc/w_inst.c config.h $(srcdir)/winrc/w_inst.h $(srcdir)/winrc/win_svc.h
unbound-service-install.lo unbound-service-install.o: $(srcdir)/winrc/unbound-service-install.c config.h \
$(srcdir)/winrc/w_inst.h
@@ -1213,3 +1240,4 @@ arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c config.h $(srcdir)/util/l
sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h
reallocarray.lo reallocarray.o: $(srcdir)/compat/reallocarray.c config.h
isblank.lo isblank.o: $(srcdir)/compat/isblank.c config.h
+strsep.lo strsep.o: $(srcdir)/compat/strsep.c config.h
diff --git a/contrib/unbound/acx_nlnetlabs.m4 b/contrib/unbound/acx_nlnetlabs.m4
index d43b66e..a6c174f 100644
--- a/contrib/unbound/acx_nlnetlabs.m4
+++ b/contrib/unbound/acx_nlnetlabs.m4
@@ -2,7 +2,9 @@
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
# BSD licensed.
#
-# Version 32
+# Version 34
+# 2016-03-21 Check -ldl -pthread for libcrypto for ldns and openssl 1.1.0.
+# 2016-03-21 Use HMAC_Update instead of HMAC_CTX_Init (for openssl-1.1.0).
# 2016-01-04 -D_DEFAULT_SOURCE defined with -D_BSD_SOURCE for Linux glibc 2.20
# 2015-12-11 FLTO check for new OSX, clang.
# 2015-11-18 spelling check fix.
@@ -671,16 +673,16 @@ AC_DEFUN([ACX_SSL_CHECKS], [
ACX_RUNTIME_PATH_ADD([$ssldir/lib])
fi
- AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto])
+ AC_MSG_CHECKING([for HMAC_Update in -lcrypto])
LIBS="$LIBS -lcrypto"
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
AC_TRY_LINK(, [
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
], [
AC_MSG_RESULT(yes)
- AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
- [If you have HMAC_CTX_init])
+ AC_DEFINE([HAVE_HMAC_UPDATE], 1,
+ [If you have HMAC_Update])
], [
AC_MSG_RESULT(no)
# check if -lwsock32 or -lgdi32 are needed.
@@ -690,11 +692,11 @@ AC_DEFUN([ACX_SSL_CHECKS], [
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32"
AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
AC_TRY_LINK([], [
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
],[
- AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
- [If you have HMAC_CTX_init])
+ AC_DEFINE([HAVE_HMAC_UPDATE], 1,
+ [If you have HMAC_Update])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
@@ -704,15 +706,30 @@ AC_DEFUN([ACX_SSL_CHECKS], [
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
AC_MSG_CHECKING([if -lcrypto needs -ldl])
AC_TRY_LINK([], [
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
],[
- AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
- [If you have HMAC_CTX_init])
+ AC_DEFINE([HAVE_HMAC_UPDATE], 1,
+ [If you have HMAC_Update])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
- AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
+ LIBS="$BAKLIBS"
+ LIBSSL_LIBS="$BAKSSLLIBS"
+ LIBS="$LIBS -ldl -pthread"
+ LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
+ AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
+ AC_TRY_LINK([], [
+ int HMAC_Update(void);
+ (void)HMAC_Update();
+ ],[
+ AC_DEFINE([HAVE_HMAC_UPDATE], 1,
+ [If you have HMAC_Update])
+ AC_MSG_RESULT(yes)
+ ],[
+ AC_MSG_RESULT(no)
+ AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
+ ])
])
])
])
diff --git a/contrib/unbound/acx_python.m4 b/contrib/unbound/acx_python.m4
index 254ff20..4e83d77 100644
--- a/contrib/unbound/acx_python.m4
+++ b/contrib/unbound/acx_python.m4
@@ -54,7 +54,7 @@ $ac_distutils_result])
AC_MSG_CHECKING([for Python library path])
if test -z "$PYTHON_LDFLAGS"; then
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
- print(get_config_var('BLDLIBRARY'));"`
+ print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"`
fi
AC_MSG_RESULT([$PYTHON_LDFLAGS])
AC_SUBST([PYTHON_LDFLAGS])
diff --git a/contrib/unbound/cachedb/cachedb.c b/contrib/unbound/cachedb/cachedb.c
new file mode 100644
index 0000000..76d9afa
--- /dev/null
+++ b/contrib/unbound/cachedb/cachedb.c
@@ -0,0 +1,702 @@
+/*
+ * cachedb/cachedb.c - cache from a database external to the program module
+ *
+ * Copyright (c) 2016, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * 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 of the NLNET LABS 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
+ * HOLDER 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.
+ */
+
+/**
+ * \file
+ *
+ * This file contains a module that uses an external database to cache
+ * dns responses.
+ */
+
+#include "config.h"
+#ifdef USE_CACHEDB
+#include "cachedb/cachedb.h"
+#include "util/regional.h"
+#include "util/net_help.h"
+#include "util/config_file.h"
+#include "util/data/msgreply.h"
+#include "util/data/msgencode.h"
+#include "services/cache/dns.h"
+#include "validator/val_neg.h"
+#include "validator/val_secalgo.h"
+#include "iterator/iter_utils.h"
+#include "sldns/parseutil.h"
+#include "sldns/wire2str.h"
+#include "sldns/sbuffer.h"
+
+#define CACHEDB_HASHSIZE 256 /* bit hash */
+
+/** the unit test testframe for cachedb, its module state contains
+ * a cache for a couple queries (in memory). */
+struct testframe_moddata {
+ /** key for single stored data element, NULL if none */
+ char* stored_key;
+ /** data for single stored data element, NULL if none */
+ uint8_t* stored_data;
+ /** length of stored data */
+ size_t stored_datalen;
+};
+
+static int
+testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
+{
+ (void)env;
+ verbose(VERB_ALGO, "testframe_init");
+ cachedb_env->backend_data = (void*)calloc(1,
+ sizeof(struct testframe_moddata));
+ if(!cachedb_env->backend_data) {
+ log_err("out of memory");
+ return 0;
+ }
+ return 1;
+}
+
+static void
+testframe_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
+{
+ struct testframe_moddata* d = (struct testframe_moddata*)
+ cachedb_env->backend_data;
+ (void)env;
+ verbose(VERB_ALGO, "testframe_deinit");
+ if(!d)
+ return;
+ free(d->stored_key);
+ free(d->stored_data);
+ free(d);
+}
+
+static int
+testframe_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
+ char* key, struct sldns_buffer* result_buffer)
+{
+ struct testframe_moddata* d = (struct testframe_moddata*)
+ cachedb_env->backend_data;
+ (void)env;
+ verbose(VERB_ALGO, "testframe_lookup of %s", key);
+ if(d->stored_key && strcmp(d->stored_key, key) == 0) {
+ if(d->stored_datalen > sldns_buffer_capacity(result_buffer))
+ return 0; /* too large */
+ verbose(VERB_ALGO, "testframe_lookup found %d bytes",
+ (int)d->stored_datalen);
+ sldns_buffer_clear(result_buffer);
+ sldns_buffer_write(result_buffer, d->stored_data,
+ d->stored_datalen);
+ sldns_buffer_flip(result_buffer);
+ return 1;
+ }
+ return 0;
+}
+
+static void
+testframe_store(struct module_env* env, struct cachedb_env* cachedb_env,
+ char* key, uint8_t* data, size_t data_len)
+{
+ struct testframe_moddata* d = (struct testframe_moddata*)
+ cachedb_env->backend_data;
+ (void)env;
+ verbose(VERB_ALGO, "testframe_store %s (%d bytes)", key, (int)data_len);
+
+ /* free old data element (if any) */
+ free(d->stored_key);
+ d->stored_key = NULL;
+ free(d->stored_data);
+ d->stored_data = NULL;
+ d->stored_datalen = 0;
+
+ d->stored_data = memdup(data, data_len);
+ if(!d->stored_data) {
+ log_err("out of memory");
+ return;
+ }
+ d->stored_datalen = data_len;
+ d->stored_key = strdup(key);
+ if(!d->stored_key) {
+ free(d->stored_data);
+ d->stored_data = NULL;
+ d->stored_datalen = 0;
+ return;
+ }
+ /* (key,data) successfully stored */
+}
+
+/** The testframe backend is for unit tests */
+static struct cachedb_backend testframe_backend = { "testframe",
+ testframe_init, testframe_deinit, testframe_lookup, testframe_store
+};
+
+/** find a particular backend from possible backends */
+static struct cachedb_backend*
+cachedb_find_backend(const char* str)
+{
+ if(strcmp(str, testframe_backend.name) == 0)
+ return &testframe_backend;
+ /* TODO add more backends here */
+ return NULL;
+}
+
+/** apply configuration to cachedb module 'global' state */
+static int
+cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
+{
+ const char* backend_str = "testframe"; /* TODO get from cfg */
+ if(backend_str && backend_str[0]) {
+ cachedb_env->backend = cachedb_find_backend(backend_str);
+ if(!cachedb_env->backend) {
+ log_err("cachedb: cannot find backend name '%s",
+ backend_str);
+ return NULL;
+ }
+ }
+ /* TODO see if more configuration needs to be applied or not */
+ return 1;
+}
+
+int
+cachedb_init(struct module_env* env, int id)
+{
+ struct cachedb_env* cachedb_env = (struct cachedb_env*)calloc(1,
+ sizeof(struct cachedb_env));
+ if(!cachedb_env) {
+ log_err("malloc failure");
+ return 0;
+ }
+ env->modinfo[id] = (void*)cachedb_env;
+ if(!cachedb_apply_cfg(cachedb_env, env->cfg)) {
+ log_err("cachedb: could not apply configuration settings.");
+ return 0;
+ }
+ /* see if a backend is selected */
+ if(!cachedb_env->backend || !cachedb_env->backend->name)
+ return 1;
+ if(!(*cachedb_env->backend->init)(env, cachedb_env)) {
+ log_err("cachedb: could not init %s backend",
+ cachedb_env->backend->name);
+ return 0;
+ }
+ cachedb_env->enabled = 1;
+ return 1;
+}
+
+void
+cachedb_deinit(struct module_env* env, int id)
+{
+ struct cachedb_env* cachedb_env;
+ if(!env || !env->modinfo[id])
+ return;
+ cachedb_env = (struct cachedb_env*)env->modinfo[id];
+ /* free contents */
+ /* TODO */
+ if(cachedb_env->enabled) {
+ (*cachedb_env->backend->deinit)(env, cachedb_env);
+ }
+
+ free(cachedb_env);
+ env->modinfo[id] = NULL;
+}
+
+/** new query for cachedb */
+static int
+cachedb_new(struct module_qstate* qstate, int id)
+{
+ struct cachedb_qstate* iq = (struct cachedb_qstate*)regional_alloc(
+ qstate->region, sizeof(struct cachedb_qstate));
+ qstate->minfo[id] = iq;
+ if(!iq)
+ return 0;
+ memset(iq, 0, sizeof(*iq));
+ /* initialise it */
+ /* TODO */
+
+ return 1;
+}
+
+/**
+ * Return an error
+ * @param qstate: our query state
+ * @param id: module id
+ * @param rcode: error code (DNS errcode).
+ * @return: 0 for use by caller, to make notation easy, like:
+ * return error_response(..).
+ */
+static int
+error_response(struct module_qstate* qstate, int id, int rcode)
+{
+ verbose(VERB_QUERY, "return error response %s",
+ sldns_lookup_by_id(sldns_rcodes, rcode)?
+ sldns_lookup_by_id(sldns_rcodes, rcode)->name:"??");
+ qstate->return_rcode = rcode;
+ qstate->return_msg = NULL;
+ qstate->ext_state[id] = module_finished;
+ return 0;
+}
+
+/**
+ * Hash the query name, type, class and dbacess-secret into lookup buffer.
+ * @param qstate: query state with query info
+ * and env->cfg with secret.
+ * @param buf: returned buffer with hash to lookup
+ * @param len: length of the buffer.
+ */
+static void
+calc_hash(struct module_qstate* qstate, char* buf, size_t len)
+{
+ uint8_t clear[1024];
+ size_t clen = 0;
+ uint8_t hash[CACHEDB_HASHSIZE/8];
+ const char* hex = "0123456789ABCDEF";
+ const char* secret = "default"; /* TODO: from qstate->env->cfg */
+ size_t i;
+
+ /* copy the hash info into the clear buffer */
+ if(clen + qstate->qinfo.qname_len < sizeof(clear)) {
+ memmove(clear+clen, qstate->qinfo.qname,
+ qstate->qinfo.qname_len);
+ clen += qstate->qinfo.qname_len;
+ }
+ if(clen + 4 < sizeof(clear)) {
+ uint16_t t = htons(qstate->qinfo.qtype);
+ uint16_t c = htons(qstate->qinfo.qclass);
+ memmove(clear+clen, &t, 2);
+ memmove(clear+clen+2, &c, 2);
+ clen += 4;
+ }
+ if(secret && secret[0] && clen + strlen(secret) < sizeof(clear)) {
+ memmove(clear+clen, secret, strlen(secret));
+ clen += strlen(secret);
+ }
+
+ /* hash the buffer */
+ secalgo_hash_sha256(clear, clen, hash);
+ memset(clear, 0, clen);
+
+ /* hex encode output for portability (some online dbs need
+ * no nulls, no control characters, and so on) */
+ log_assert(len >= sizeof(hash)*2 + 1);
+ (void)len;
+ for(i=0; i<sizeof(hash); i++) {
+ buf[i*2] = hex[(hash[i]&0xf0)>>4];
+ buf[i*2+1] = hex[hash[i]&0x0f];
+ }
+ buf[sizeof(hash)*2] = 0;
+}
+
+/** convert data from return_msg into the data buffer */
+static int
+prep_data(struct module_qstate* qstate, struct sldns_buffer* buf)
+{
+ uint64_t timestamp, expiry;
+ size_t oldlim;
+ struct edns_data edns;
+ memset(&edns, 0, sizeof(edns));
+ edns.edns_present = 1;
+ edns.bits = EDNS_DO;
+ edns.ext_rcode = 0;
+ edns.edns_version = EDNS_ADVERTISED_VERSION;
+ edns.udp_size = EDNS_ADVERTISED_SIZE;
+
+ if(!qstate->return_msg || !qstate->return_msg->rep)
+ return 0;
+ if(verbosity >= VERB_ALGO)
+ log_dns_msg("cachedb encoding", &qstate->return_msg->qinfo,
+ qstate->return_msg->rep);
+ if(!reply_info_answer_encode(&qstate->return_msg->qinfo,
+ qstate->return_msg->rep, 0, qstate->query_flags,
+ buf, 0, 1, qstate->env->scratch, 65535, &edns, 1, 0))
+ return 0;
+
+ /* TTLs in the return_msg are relative to time(0) so we have to
+ * store that, we also store the smallest ttl in the packet+time(0)
+ * as the packet expiry time */
+ /* qstate->return_msg->rep->ttl contains that relative shortest ttl */
+ timestamp = (uint64_t)*qstate->env->now;
+ expiry = timestamp + (uint64_t)qstate->return_msg->rep->ttl;
+ timestamp = htobe64(timestamp);
+ expiry = htobe64(expiry);
+ oldlim = sldns_buffer_limit(buf);
+ if(oldlim + sizeof(timestamp)+sizeof(expiry) >=
+ sldns_buffer_capacity(buf))
+ return 0; /* doesn't fit. */
+ sldns_buffer_set_limit(buf, oldlim + sizeof(timestamp)+sizeof(expiry));
+ sldns_buffer_write_at(buf, oldlim, &timestamp, sizeof(timestamp));
+ sldns_buffer_write_at(buf, oldlim+sizeof(timestamp), &expiry,
+ sizeof(expiry));
+
+ return 1;
+}
+
+/** check expiry, return true if matches OK */
+static int
+good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
+{
+ uint64_t expiry;
+ /* the expiry time is the last bytes of the buffer */
+ if(sldns_buffer_limit(buf) < sizeof(expiry))
+ return 0;
+ sldns_buffer_read_at(buf, sldns_buffer_limit(buf)-sizeof(expiry),
+ &expiry, sizeof(expiry));
+ expiry = be64toh(expiry);
+
+ if((time_t)expiry < *qstate->env->now)
+ return 0;
+
+ return 1;
+}
+
+/** convert dns message in buffer to return_msg */
+static int
+parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
+{
+ struct msg_parse* prs;
+ struct edns_data edns;
+ uint64_t timestamp, expiry;
+ time_t adjust;
+ size_t lim = sldns_buffer_limit(buf);
+ if(lim < LDNS_HEADER_SIZE+sizeof(timestamp)+sizeof(expiry))
+ return 0; /* too short */
+
+ /* remove timestamp and expiry from end */
+ sldns_buffer_read_at(buf, lim-sizeof(expiry), &expiry, sizeof(expiry));
+ sldns_buffer_read_at(buf, lim-sizeof(expiry)-sizeof(timestamp),
+ &timestamp, sizeof(timestamp));
+ expiry = be64toh(expiry);
+ timestamp = be64toh(timestamp);
+
+ /* parse DNS packet */
+ regional_free_all(qstate->env->scratch);
+ prs = (struct msg_parse*)regional_alloc(qstate->env->scratch,
+ sizeof(struct msg_parse));
+ if(!prs)
+ return 0; /* out of memory */
+ memset(prs, 0, sizeof(*prs));
+ memset(&edns, 0, sizeof(edns));
+ sldns_buffer_set_limit(buf, lim - sizeof(expiry)-sizeof(timestamp));
+ if(parse_packet(buf, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
+ sldns_buffer_set_limit(buf, lim);
+ return 0;
+ }
+ if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
+ LDNS_RCODE_NOERROR) {
+ sldns_buffer_set_limit(buf, lim);
+ return 0;
+ }
+
+ qstate->return_msg = dns_alloc_msg(buf, prs, qstate->region);
+ sldns_buffer_set_limit(buf, lim);
+ if(!qstate->return_msg)
+ return 0;
+
+ qstate->return_rcode = LDNS_RCODE_NOERROR;
+
+ /* see how much of the TTL expired, and remove it */
+ adjust = *qstate->env->now - (time_t)timestamp;
+ verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
+ /*adjust_msg(qstate->return_msg, adjust);*/
+ /* TODO:
+ msg->rep->ttl = r->ttl - adjust;
+ msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
+ for(i=0; i<d->count + d->rrsig_count; i++) {
+ if(d->rr_ttl[i] < adjust)
+ d->rr_ttl[i] = 0;
+ else d->rr_ttl[i] -= adjust;
+ }
+ if(d->ttl < adjust)
+ d->ttl = 0;
+ else d->ttl -= adjust;
+ */
+ /* TODO */
+
+ return 0;
+}
+
+/**
+ * Lookup the qstate.qinfo in extcache, store in qstate.return_msg.
+ * return true if lookup was successful.
+ */
+static int
+cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
+{
+ char key[(CACHEDB_HASHSIZE/8)*2+1];
+ calc_hash(qstate, key, sizeof(key));
+
+ /* call backend to fetch data for key into scratch buffer */
+ if( !(*ie->backend->lookup)(qstate->env, ie, key,
+ qstate->env->scratch_buffer)) {
+ return 0;
+ }
+
+ /* check expiry date and check if query-data matches */
+ if( !good_expiry_and_qinfo(qstate, qstate->env->scratch_buffer) ) {
+ return 0;
+ }
+
+ /* parse dns message into return_msg */
+ if( !parse_data(qstate, qstate->env->scratch_buffer) ) {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Store the qstate.return_msg in extcache for key qstate.info
+ */
+static void
+cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
+{
+ char key[(CACHEDB_HASHSIZE/8)*2+1];
+ calc_hash(qstate, key, sizeof(key));
+
+ /* prepare data in scratch buffer */
+ if(!prep_data(qstate, qstate->env->scratch_buffer))
+ return;
+
+ /* call backend */
+ (*ie->backend->store)(qstate->env, ie, key,
+ sldns_buffer_begin(qstate->env->scratch_buffer),
+ sldns_buffer_limit(qstate->env->scratch_buffer));
+}
+
+/**
+ * See if unbound's internal cache can answer the query
+ */
+static int
+cachedb_intcache_lookup(struct module_qstate* qstate)
+{
+ struct dns_msg* msg;
+ msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
+ qstate->qinfo.qname_len, qstate->qinfo.qtype,
+ qstate->qinfo.qclass, qstate->query_flags,
+ qstate->region, qstate->env->scratch);
+ if(!msg && qstate->env->neg_cache) {
+ /* lookup in negative cache; may result in
+ * NOERROR/NODATA or NXDOMAIN answers that need validation */
+ msg = val_neg_getmsg(qstate->env->neg_cache, &qstate->qinfo,
+ qstate->region, qstate->env->rrset_cache,
+ qstate->env->scratch_buffer,
+ *qstate->env->now, 1/*add SOA*/, NULL);
+ }
+ if(!msg)
+ return 0;
+ /* this is the returned msg */
+ qstate->return_rcode = LDNS_RCODE_NOERROR;
+ qstate->return_msg = msg;
+ return 1;
+}
+
+/**
+ * Store query into the internal cache of unbound.
+ */
+static void
+cachedb_intcache_store(struct module_qstate* qstate)
+{
+ if(!qstate->return_msg)
+ return;
+ (void)dns_cache_store(qstate->env, &qstate->qinfo,
+ qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
+ qstate->region, qstate->query_flags);
+}
+
+/**
+ * Handle a cachedb module event with a query
+ * @param qstate: query state (from the mesh), passed between modules.
+ * contains qstate->env module environment with global caches and so on.
+ * @param iq: query state specific for this module. per-query.
+ * @param ie: environment specific for this module. global.
+ * @param id: module id.
+ */
+static void
+cachedb_handle_query(struct module_qstate* qstate,
+ struct cachedb_qstate* ATTR_UNUSED(iq),
+ struct cachedb_env* ie, int id)
+{
+ /* check if we are enabled, and skip if so */
+ if(!ie->enabled) {
+ /* pass request to next module */
+ qstate->ext_state[id] = module_wait_module;
+ return;
+ }
+
+ if(qstate->blacklist) {
+ /* cache is blacklisted */
+ /* pass request to next module */
+ qstate->ext_state[id] = module_wait_module;
+ return;
+ }
+
+ /* lookup inside unbound's internal cache */
+ if(cachedb_intcache_lookup(qstate)) {
+ if(verbosity >= VERB_ALGO)
+ log_dns_msg("cachedb internal cache lookup",
+ &qstate->return_msg->qinfo,
+ qstate->return_msg->rep);
+ /* we are done with the query */
+ qstate->ext_state[id] = module_finished;
+ return;
+ }
+
+ /* ask backend cache to see if we have data */
+ if(cachedb_extcache_lookup(qstate, ie)) {
+ if(verbosity >= VERB_ALGO)
+ log_dns_msg(ie->backend->name,
+ &qstate->return_msg->qinfo,
+ qstate->return_msg->rep);
+ /* store this result in internal cache */
+ cachedb_intcache_store(qstate);
+ /* we are done with the query */
+ qstate->ext_state[id] = module_finished;
+ return;
+ }
+
+ /* no cache fetches */
+ /* pass request to next module */
+ qstate->ext_state[id] = module_wait_module;
+}
+
+/**
+ * Handle a cachedb module event with a response from the iterator.
+ * @param qstate: query state (from the mesh), passed between modules.
+ * contains qstate->env module environment with global caches and so on.
+ * @param iq: query state specific for this module. per-query.
+ * @param ie: environment specific for this module. global.
+ * @param id: module id.
+ */
+static void
+cachedb_handle_response(struct module_qstate* qstate,
+ struct cachedb_qstate* ATTR_UNUSED(iq), struct cachedb_env* ie, int id)
+{
+ /* check if we are enabled, and skip if not */
+ if(!ie->enabled) {
+ /* we are done with the query */
+ qstate->ext_state[id] = module_finished;
+ return;
+ }
+
+ /* store the item into the backend cache */
+ cachedb_extcache_store(qstate, ie);
+
+ /* we are done with the query */
+ qstate->ext_state[id] = module_finished;
+}
+
+void
+cachedb_operate(struct module_qstate* qstate, enum module_ev event, int id,
+ struct outbound_entry* outbound)
+{
+ struct cachedb_env* ie = (struct cachedb_env*)qstate->env->modinfo[id];
+ struct cachedb_qstate* iq = (struct cachedb_qstate*)qstate->minfo[id];
+ verbose(VERB_QUERY, "cachedb[module %d] operate: extstate:%s event:%s",
+ id, strextstate(qstate->ext_state[id]), strmodulevent(event));
+ if(iq) log_query_info(VERB_QUERY, "cachedb operate: query",
+ &qstate->qinfo);
+
+ /* perform cachedb state machine */
+ if((event == module_event_new || event == module_event_pass) &&
+ iq == NULL) {
+ if(!cachedb_new(qstate, id)) {
+ (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ return;
+ }
+ iq = (struct cachedb_qstate*)qstate->minfo[id];
+ }
+ if(iq && (event == module_event_pass || event == module_event_new)) {
+ cachedb_handle_query(qstate, iq, ie, id);
+ return;
+ }
+ if(iq && (event == module_event_moddone)) {
+ cachedb_handle_response(qstate, iq, ie, id);
+ return;
+ }
+ if(iq && outbound) {
+ /* cachedb does not need to process responses at this time
+ * ignore it.
+ cachedb_process_response(qstate, iq, ie, id, outbound, event);
+ */
+ return;
+ }
+ if(event == module_event_error) {
+ verbose(VERB_ALGO, "got called with event error, giving up");
+ (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ return;
+ }
+
+ log_err("bad event for cachedb");
+ (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+}
+
+void
+cachedb_inform_super(struct module_qstate* ATTR_UNUSED(qstate),
+ int ATTR_UNUSED(id), struct module_qstate* ATTR_UNUSED(super))
+{
+ /* cachedb does not use subordinate requests at this time */
+ verbose(VERB_ALGO, "cachedb inform_super was called");
+}
+
+void
+cachedb_clear(struct module_qstate* qstate, int id)
+{
+ struct cachedb_qstate* iq;
+ if(!qstate)
+ return;
+ iq = (struct cachedb_qstate*)qstate->minfo[id];
+ if(iq) {
+ /* free contents of iq */
+ /* TODO */
+ }
+ qstate->minfo[id] = NULL;
+}
+
+size_t
+cachedb_get_mem(struct module_env* env, int id)
+{
+ struct cachedb_env* ie = (struct cachedb_env*)env->modinfo[id];
+ if(!ie)
+ return 0;
+ return sizeof(*ie); /* TODO - more mem */
+}
+
+/**
+ * The cachedb function block
+ */
+static struct module_func_block cachedb_block = {
+ "cachedb",
+ &cachedb_init, &cachedb_deinit, &cachedb_operate,
+ &cachedb_inform_super, &cachedb_clear, &cachedb_get_mem
+};
+
+struct module_func_block*
+cachedb_get_funcblock(void)
+{
+ return &cachedb_block;
+}
+#endif /* USE_CACHEDB */
diff --git a/contrib/unbound/cachedb/cachedb.h b/contrib/unbound/cachedb/cachedb.h
new file mode 100644
index 0000000..d477e90
--- /dev/null
+++ b/contrib/unbound/cachedb/cachedb.h
@@ -0,0 +1,110 @@
+/*
+ * cachedb/cachedb.h - cache from a database external to the program module
+ *
+ * Copyright (c) 2016, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * 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 of the NLNET LABS 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
+ * HOLDER 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.
+ */
+
+/**
+ * \file
+ *
+ * This file contains a module that uses an external database to cache
+ * dns responses.
+ */
+#include "util/module.h"
+struct cachedb_backend;
+
+/**
+ * The global variable environment contents for the cachedb
+ * Shared between threads, this represents long term information.
+ * Like database connections.
+ */
+struct cachedb_env {
+ /** true is cachedb is enabled, the backend is turned on */
+ int enabled;
+
+ /** the backend routines */
+ struct cachedb_backend* backend;
+
+ /** backend specific data here */
+ void* backend_data;
+};
+
+/**
+ * Per query state for the cachedb module.
+ */
+struct cachedb_qstate {
+ int todo;
+};
+
+/**
+ * Backend call routines
+ */
+struct cachedb_backend {
+ /** backend name */
+ const char* name;
+
+ /** Init(env, cachedb_env): false on setup failure */
+ int (*init)(struct module_env*, struct cachedb_env*);
+
+ /** Deinit - close db for program exit */
+ void (*deinit)(struct module_env*, struct cachedb_env*);
+
+ /** Lookup (env, cachedb_env, key, result_buffer): true if found */
+ int (*lookup)(struct module_env*, struct cachedb_env*, char*,
+ struct sldns_buffer*);
+
+ /** Store (env, cachedb_env, key, data, data_len) */
+ void (*store)(struct module_env*, struct cachedb_env*, char*,
+ uint8_t*, size_t);
+};
+
+/** Init the cachedb module */
+int cachedb_init(struct module_env* env, int id);
+/** Deinit the cachedb module */
+void cachedb_deinit(struct module_env* env, int id);
+/** Operate on an event on a query (in qstate). */
+void cachedb_operate(struct module_qstate* qstate, enum module_ev event,
+ int id, struct outbound_entry* outbound);
+/** Subordinate query done, inform this super request of its conclusion */
+void cachedb_inform_super(struct module_qstate* qstate, int id,
+ struct module_qstate* super);
+/** clear the cachedb query-specific contents out of qstate */
+void cachedb_clear(struct module_qstate* qstate, int id);
+/** return memory estimate for cachedb module */
+size_t cachedb_get_mem(struct module_env* env, int id);
+
+/**
+ * Get the function block with pointers to the cachedb functions
+ * @return the function block for "cachedb".
+ */
+struct module_func_block* cachedb_get_funcblock(void);
+
diff --git a/contrib/unbound/compat/arc4random.c b/contrib/unbound/compat/arc4random.c
index 2c859f1..a09665c 100644
--- a/contrib/unbound/compat/arc4random.c
+++ b/contrib/unbound/compat/arc4random.c
@@ -48,6 +48,9 @@
#else /* !__GNUC__ */
#define inline
#endif /* !__GNUC__ */
+#ifndef MAP_ANON
+#define MAP_ANON MAP_ANONYMOUS
+#endif
#define KEYSZ 32
#define IVSZ 8
diff --git a/contrib/unbound/compat/explicit_bzero.c b/contrib/unbound/compat/explicit_bzero.c
index a3ba279..5f1c427 100644
--- a/contrib/unbound/compat/explicit_bzero.c
+++ b/contrib/unbound/compat/explicit_bzero.c
@@ -6,7 +6,11 @@
#include "config.h"
#include <string.h>
+#ifdef HAVE_ATTR_WEAK
__attribute__((weak)) void
+#else
+void
+#endif
__explicit_bzero_hook(void *ATTR_UNUSED(buf), size_t ATTR_UNUSED(len))
{
}
diff --git a/contrib/unbound/compat/getentropy_linux.c b/contrib/unbound/compat/getentropy_linux.c
index 37d86a8..b86c0fb 100644
--- a/contrib/unbound/compat/getentropy_linux.c
+++ b/contrib/unbound/compat/getentropy_linux.c
@@ -60,6 +60,9 @@
#include <sys/auxv.h>
#endif
#include <sys/vfs.h>
+#ifndef MAP_ANON
+#define MAP_ANON MAP_ANONYMOUS
+#endif
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
@@ -94,7 +97,7 @@ int getentropy(void *buf, size_t len);
extern int main(int, char *argv[]);
#endif
static int gotdata(char *buf, size_t len);
-#ifdef SYS_getrandom
+#if defined(SYS_getrandom) && defined(__NR_getrandom)
static int getentropy_getrandom(void *buf, size_t len);
#endif
static int getentropy_urandom(void *buf, size_t len);
@@ -113,7 +116,7 @@ getentropy(void *buf, size_t len)
return -1;
}
-#ifdef SYS_getrandom
+#if defined(SYS_getrandom) && defined(__NR_getrandom)
/*
* Try descriptor-less getrandom()
*/
@@ -209,7 +212,7 @@ gotdata(char *buf, size_t len)
return 0;
}
-#ifdef SYS_getrandom
+#if defined(SYS_getrandom) && defined(__NR_getrandom)
static int
getentropy_getrandom(void *buf, size_t len)
{
diff --git a/contrib/unbound/compat/strsep.c b/contrib/unbound/compat/strsep.c
new file mode 100644
index 0000000..4e3f05c
--- /dev/null
+++ b/contrib/unbound/compat/strsep.c
@@ -0,0 +1,65 @@
+/**
+ * strsep implementation for compatibility.
+ *
+ * LICENSE
+ * Copyright (c) 2016, NLnet Labs
+ * 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 of NLnetLabs 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 "config.h"
+
+/** see if character is in the delimiter array */
+static int
+in_delim(char c, const char* delim)
+{
+ const char* p;
+ if(!delim)
+ return 0;
+ for(p=delim; *p; p++) {
+ if(*p == c)
+ return 1;
+ }
+ return 0;
+}
+
+char *strsep(char **stringp, const char *delim)
+{
+ char* s;
+ char* orig;
+ if(stringp == NULL || *stringp == NULL)
+ return NULL;
+ orig = *stringp;
+ s = *stringp;
+ while(*s && !in_delim(*s, delim))
+ s++;
+ if(*s) {
+ *s = 0;
+ *stringp = s+1;
+ } else {
+ *stringp = NULL;
+ }
+ return orig;
+}
diff --git a/contrib/unbound/config.h b/contrib/unbound/config.h
index 6e2a875..c8c0cf7 100644
--- a/contrib/unbound/config.h
+++ b/contrib/unbound/config.h
@@ -43,12 +43,18 @@
/* Whether the C compiler accepts the "unused" attribute */
#define HAVE_ATTR_UNUSED 1
+/* Whether the C compiler accepts the "weak" attribute */
+#define HAVE_ATTR_WEAK 1
+
/* Define to 1 if you have the `chown' function. */
#define HAVE_CHOWN 1
/* Define to 1 if you have the `chroot' function. */
#define HAVE_CHROOT 1
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+
/* Define to 1 if you have the `ctime_r' function. */
#define HAVE_CTIME_R 1
@@ -108,9 +114,18 @@
/* Define to 1 if you have the `endprotoent' function. */
#define HAVE_ENDPROTOENT 1
+/* Define to 1 if you have the `endpwent' function. */
+#define HAVE_ENDPWENT 1
+
/* Define to 1 if you have the `endservent' function. */
#define HAVE_ENDSERVENT 1
+/* Define to 1 if you have the `ERR_free_strings' function. */
+#define HAVE_ERR_FREE_STRINGS 1
+
+/* Define to 1 if you have the `ERR_load_crypto_strings' function. */
+#define HAVE_ERR_LOAD_CRYPTO_STRINGS 1
+
/* Define to 1 if you have the `event_base_free' function. */
/* #undef HAVE_EVENT_BASE_FREE */
@@ -126,6 +141,12 @@
/* Define to 1 if you have the <event.h> header file. */
/* #undef HAVE_EVENT_H */
+/* Define to 1 if you have the `EVP_cleanup' function. */
+#define HAVE_EVP_CLEANUP 1
+
+/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
+/* #undef HAVE_EVP_MD_CTX_NEW */
+
/* Define to 1 if you have the `EVP_sha1' function. */
#define HAVE_EVP_SHA1 1
@@ -189,8 +210,8 @@
/* Define to 1 if you have the <grp.h> header file. */
#define HAVE_GRP_H 1
-/* If you have HMAC_CTX_init */
-#define HAVE_HMAC_CTX_INIT 1
+/* If you have HMAC_Update */
+#define HAVE_HMAC_UPDATE 1
/* Define to 1 if you have the `inet_aton' function. */
#define HAVE_INET_ATON 1
@@ -249,24 +270,48 @@
/* Use libnettle for crypto */
/* #undef HAVE_NETTLE */
+/* Define to 1 if you have the <nettle/dsa-compat.h> header file. */
+/* #undef HAVE_NETTLE_DSA_COMPAT_H */
+
/* Use libnss for crypto */
/* #undef HAVE_NSS */
+/* Define to 1 if you have the `OpenSSL_add_all_digests' function. */
+#define HAVE_OPENSSL_ADD_ALL_DIGESTS 1
+
+/* Define to 1 if you have the <openssl/bn.h> header file. */
+#define HAVE_OPENSSL_BN_H 1
+
/* Define to 1 if you have the `OPENSSL_config' function. */
#define HAVE_OPENSSL_CONFIG 1
/* Define to 1 if you have the <openssl/conf.h> header file. */
#define HAVE_OPENSSL_CONF_H 1
+/* Define to 1 if you have the <openssl/dh.h> header file. */
+#define HAVE_OPENSSL_DH_H 1
+
+/* Define to 1 if you have the <openssl/dsa.h> header file. */
+#define HAVE_OPENSSL_DSA_H 1
+
/* Define to 1 if you have the <openssl/engine.h> header file. */
#define HAVE_OPENSSL_ENGINE_H 1
/* Define to 1 if you have the <openssl/err.h> header file. */
#define HAVE_OPENSSL_ERR_H 1
+/* Define to 1 if you have the `OPENSSL_init_crypto' function. */
+/* #undef HAVE_OPENSSL_INIT_CRYPTO */
+
+/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
+/* #undef HAVE_OPENSSL_INIT_SSL */
+
/* Define to 1 if you have the <openssl/rand.h> header file. */
#define HAVE_OPENSSL_RAND_H 1
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+#define HAVE_OPENSSL_RSA_H 1
+
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#define HAVE_OPENSSL_SSL_H 1
@@ -291,6 +336,9 @@
/* Define to 1 if you have the `random' function. */
#define HAVE_RANDOM 1
+/* Define to 1 if you have the `RAND_cleanup' function. */
+#define HAVE_RAND_CLEANUP 1
+
/* Define to 1 if you have the `reallocarray' function. */
#define HAVE_REALLOCARRAY 1
@@ -378,6 +426,9 @@
/* Define to 1 if you have the `strptime' function. */
#define HAVE_STRPTIME 1
+/* Define to 1 if you have the `strsep' function. */
+#define HAVE_STRSEP 1
+
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
/* #undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST */
@@ -515,7 +566,7 @@
#define PACKAGE_NAME "unbound"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "unbound 1.5.8"
+#define PACKAGE_STRING "unbound 1.5.10"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unbound"
@@ -524,7 +575,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.5.8"
+#define PACKAGE_VERSION "1.5.10"
/* default pidfile location */
#define PIDFILE "/var/unbound/unbound.pid"
@@ -543,7 +594,7 @@
#define ROOT_CERT_FILE "/var/unbound/icannbundle.pem"
/* version number for resource files */
-#define RSRC_PACKAGE_VERSION 1,5,8,0
+#define RSRC_PACKAGE_VERSION 1,5,10,0
/* Directory to chdir to */
#define RUN_DIR "/var/unbound"
@@ -581,9 +632,15 @@
/* define this to enable debug checks. */
/* #undef UNBOUND_DEBUG */
+/* Define to 1 to use cachedb support */
+/* #undef USE_CACHEDB */
+
/* Define to 1 to enable dnstap support */
/* #undef USE_DNSTAP */
+/* Define this to enable DSA support. */
+#define USE_DSA 1
+
/* Define this to enable ECDSA support. */
#define USE_ECDSA 1
@@ -596,6 +653,12 @@
/* Define if you want to use internal select based events */
#define USE_MINI_EVENT 1
+/* Define this to enable client TCP Fast Open. */
+/* #undef USE_MSG_FASTOPEN */
+
+/* Define this to enable client TCP Fast Open. */
+/* #undef USE_OSX_MSG_FASTOPEN */
+
/* Define this to enable SHA256 and SHA512 support. */
#define USE_SHA2 1
@@ -621,6 +684,9 @@
#endif
+/* Define this to enable server TCP Fast Open. */
+/* #undef USE_TCP_FASTOPEN */
+
/* Whether the windows socket API is used */
/* #undef USE_WINSOCK */
@@ -980,6 +1046,11 @@ int memcmp(const void *x, const void *y, size_t n);
char *ctime_r(const time_t *timep, char *buf);
#endif
+#ifndef HAVE_STRSEP
+#define strsep unbound_strsep
+char *strsep(char **stringp, const char *delim);
+#endif
+
#ifndef HAVE_ISBLANK
#define isblank unbound_isblank
int isblank(int c);
diff --git a/contrib/unbound/config.h.in b/contrib/unbound/config.h.in
index 59277dd..04fc743 100644
--- a/contrib/unbound/config.h.in
+++ b/contrib/unbound/config.h.in
@@ -42,12 +42,18 @@
/* Whether the C compiler accepts the "unused" attribute */
#undef HAVE_ATTR_UNUSED
+/* Whether the C compiler accepts the "weak" attribute */
+#undef HAVE_ATTR_WEAK
+
/* Define to 1 if you have the `chown' function. */
#undef HAVE_CHOWN
/* Define to 1 if you have the `chroot' function. */
#undef HAVE_CHROOT
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+#undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
+
/* Define to 1 if you have the `ctime_r' function. */
#undef HAVE_CTIME_R
@@ -107,9 +113,18 @@
/* Define to 1 if you have the `endprotoent' function. */
#undef HAVE_ENDPROTOENT
+/* Define to 1 if you have the `endpwent' function. */
+#undef HAVE_ENDPWENT
+
/* Define to 1 if you have the `endservent' function. */
#undef HAVE_ENDSERVENT
+/* Define to 1 if you have the `ERR_free_strings' function. */
+#undef HAVE_ERR_FREE_STRINGS
+
+/* Define to 1 if you have the `ERR_load_crypto_strings' function. */
+#undef HAVE_ERR_LOAD_CRYPTO_STRINGS
+
/* Define to 1 if you have the `event_base_free' function. */
#undef HAVE_EVENT_BASE_FREE
@@ -125,6 +140,12 @@
/* Define to 1 if you have the <event.h> header file. */
#undef HAVE_EVENT_H
+/* Define to 1 if you have the `EVP_cleanup' function. */
+#undef HAVE_EVP_CLEANUP
+
+/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
+#undef HAVE_EVP_MD_CTX_NEW
+
/* Define to 1 if you have the `EVP_sha1' function. */
#undef HAVE_EVP_SHA1
@@ -188,8 +209,8 @@
/* Define to 1 if you have the <grp.h> header file. */
#undef HAVE_GRP_H
-/* If you have HMAC_CTX_init */
-#undef HAVE_HMAC_CTX_INIT
+/* If you have HMAC_Update */
+#undef HAVE_HMAC_UPDATE
/* Define to 1 if you have the `inet_aton' function. */
#undef HAVE_INET_ATON
@@ -248,24 +269,48 @@
/* Use libnettle for crypto */
#undef HAVE_NETTLE
+/* Define to 1 if you have the <nettle/dsa-compat.h> header file. */
+#undef HAVE_NETTLE_DSA_COMPAT_H
+
/* Use libnss for crypto */
#undef HAVE_NSS
+/* Define to 1 if you have the `OpenSSL_add_all_digests' function. */
+#undef HAVE_OPENSSL_ADD_ALL_DIGESTS
+
+/* Define to 1 if you have the <openssl/bn.h> header file. */
+#undef HAVE_OPENSSL_BN_H
+
/* Define to 1 if you have the `OPENSSL_config' function. */
#undef HAVE_OPENSSL_CONFIG
/* Define to 1 if you have the <openssl/conf.h> header file. */
#undef HAVE_OPENSSL_CONF_H
+/* Define to 1 if you have the <openssl/dh.h> header file. */
+#undef HAVE_OPENSSL_DH_H
+
+/* Define to 1 if you have the <openssl/dsa.h> header file. */
+#undef HAVE_OPENSSL_DSA_H
+
/* Define to 1 if you have the <openssl/engine.h> header file. */
#undef HAVE_OPENSSL_ENGINE_H
/* Define to 1 if you have the <openssl/err.h> header file. */
#undef HAVE_OPENSSL_ERR_H
+/* Define to 1 if you have the `OPENSSL_init_crypto' function. */
+#undef HAVE_OPENSSL_INIT_CRYPTO
+
+/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
+#undef HAVE_OPENSSL_INIT_SSL
+
/* Define to 1 if you have the <openssl/rand.h> header file. */
#undef HAVE_OPENSSL_RAND_H
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+#undef HAVE_OPENSSL_RSA_H
+
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#undef HAVE_OPENSSL_SSL_H
@@ -290,6 +335,9 @@
/* Define to 1 if you have the `random' function. */
#undef HAVE_RANDOM
+/* Define to 1 if you have the `RAND_cleanup' function. */
+#undef HAVE_RAND_CLEANUP
+
/* Define to 1 if you have the `reallocarray' function. */
#undef HAVE_REALLOCARRAY
@@ -377,6 +425,9 @@
/* Define to 1 if you have the `strptime' function. */
#undef HAVE_STRPTIME
+/* Define to 1 if you have the `strsep' function. */
+#undef HAVE_STRSEP
+
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
@@ -580,9 +631,15 @@
/* define this to enable debug checks. */
#undef UNBOUND_DEBUG
+/* Define to 1 to use cachedb support */
+#undef USE_CACHEDB
+
/* Define to 1 to enable dnstap support */
#undef USE_DNSTAP
+/* Define this to enable DSA support. */
+#undef USE_DSA
+
/* Define this to enable ECDSA support. */
#undef USE_ECDSA
@@ -595,6 +652,12 @@
/* Define if you want to use internal select based events */
#undef USE_MINI_EVENT
+/* Define this to enable client TCP Fast Open. */
+#undef USE_MSG_FASTOPEN
+
+/* Define this to enable client TCP Fast Open. */
+#undef USE_OSX_MSG_FASTOPEN
+
/* Define this to enable SHA256 and SHA512 support. */
#undef USE_SHA2
@@ -620,6 +683,9 @@
#endif
+/* Define this to enable server TCP Fast Open. */
+#undef USE_TCP_FASTOPEN
+
/* Whether the windows socket API is used */
#undef USE_WINSOCK
@@ -979,6 +1045,11 @@ int memcmp(const void *x, const void *y, size_t n);
char *ctime_r(const time_t *timep, char *buf);
#endif
+#ifndef HAVE_STRSEP
+#define strsep unbound_strsep
+char *strsep(char **stringp, const char *delim);
+#endif
+
#ifndef HAVE_ISBLANK
#define isblank unbound_isblank
int isblank(int c);
diff --git a/contrib/unbound/configure b/contrib/unbound/configure
index 6c6b9ef..54f93db 100755
--- a/contrib/unbound/configure
+++ b/contrib/unbound/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for unbound 1.5.8.
+# Generated by GNU Autoconf 2.69 for unbound 1.5.10.
#
# Report bugs to <unbound-bugs@nlnetlabs.nl>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.5.8'
-PACKAGE_STRING='unbound 1.5.8'
+PACKAGE_VERSION='1.5.10'
+PACKAGE_STRING='unbound 1.5.10'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
PACKAGE_URL=''
@@ -832,7 +832,10 @@ with_ssl
enable_sha2
enable_gost
enable_ecdsa
+enable_dsa
enable_event_api
+enable_tfo_client
+enable_tfo_server
with_libevent
with_libexpat
enable_static_exe
@@ -842,6 +845,7 @@ enable_dnstap
with_dnstap_socket_path
with_protobuf_c
with_libfstrm
+enable_cachedb
with_libunbound_only
'
ac_precious_vars='build_alias
@@ -1397,7 +1401,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures unbound 1.5.8 to adapt to many kinds of systems.
+\`configure' configures unbound 1.5.10 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1462,7 +1466,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of unbound 1.5.8:";;
+ short | recursive ) echo "Configuration of unbound 1.5.10:";;
esac
cat <<\_ACEOF
@@ -1495,8 +1499,11 @@ Optional Features:
--disable-sha2 Disable SHA256 and SHA512 RRSIG support
--disable-gost Disable GOST support
--disable-ecdsa Disable ECDSA support
- --enable-event-api Enable (experimental) libevent-based libunbound API
- installed to unbound-event.h
+ --disable-dsa Disable DSA support
+ --enable-event-api Enable (experimental) pluggable event base
+ libunbound API installed to unbound-event.h
+ --enable-tfo-client Enable TCP Fast Open for client mode
+ --enable-tfo-server Enable TCP Fast Open for server mode
--enable-static-exe enable to compile executables statically against
(event) libs, for debug purposes
--enable-lock-checks enable to check lock and unlock calls, for debug
@@ -1505,6 +1512,8 @@ Optional Features:
to it, smaller install size but libunbound export
table is polluted by internal symbols
--enable-dnstap Enable dnstap support (requires fstrm, protobuf-c)
+ --enable-cachedb enable cachedb module that can use external cache
+ storage
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1647,7 +1656,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-unbound configure 1.5.8
+unbound configure 1.5.10
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2356,7 +2365,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by unbound $as_me 1.5.8, which was
+It was created by unbound $as_me 1.5.10, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2708,11 +2717,11 @@ UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=5
-UNBOUND_VERSION_MICRO=8
+UNBOUND_VERSION_MICRO=10
LIBUNBOUND_CURRENT=6
-LIBUNBOUND_REVISION=0
+LIBUNBOUND_REVISION=2
LIBUNBOUND_AGE=4
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -2760,6 +2769,8 @@ LIBUNBOUND_AGE=4
# 1.5.6 had 5:9:3
# 1.5.7 had 5:10:3
# 1.5.8 had 6:0:4 # adds ub_ctx_set_stub
+# 1.5.9 had 6:1:4
+# 1.5.10 had 6:2:4
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -4048,7 +4059,7 @@ esac
# are we on MinGW?
if uname -s 2>&1 | grep MINGW32 >/dev/null; then on_mingw="yes"
else
- if echo $target | grep mingw32 >/dev/null; then on_mingw="yes"
+ if echo $host $target | grep mingw32 >/dev/null; then on_mingw="yes"
else on_mingw="no"; fi
fi
@@ -4058,7 +4069,7 @@ fi
if test $on_mingw = "no"; then
ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"`
else
- ub_conf_file="C:\\Program Files\\Unbound\\service.conf"
+ ub_conf_file="C:\\Program Files (x86)\\Unbound\\service.conf"
fi
# Check whether --with-conf_file was given.
@@ -4189,7 +4200,7 @@ else
if test $on_mingw = no; then
UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key"
else
- UNBOUND_ROOTKEY_FILE="C:\\Program Files\\Unbound\\root.key"
+ UNBOUND_ROOTKEY_FILE="C:\\Program Files (x86)\\Unbound\\root.key"
fi
fi
@@ -4211,7 +4222,7 @@ else
if test $on_mingw = no; then
UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem"
else
- UNBOUND_ROOTCERT_FILE="C:\\Program Files\\Unbound\\icannbundle.pem"
+ UNBOUND_ROOTCERT_FILE="C:\\Program Files (x86)\\Unbound\\icannbundle.pem"
fi
fi
@@ -6117,6 +6128,48 @@ $as_echo "#define HAVE_ATTR_UNUSED 1" >>confdefs.h
fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"weak\" attribute" >&5
+$as_echo_n "checking whether the C compiler (${CC-cc}) accepts the \"weak\" attribute... " >&6; }
+if ${ac_cv_c_weak_attribute+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_weak_attribute=no
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+ #include <stdio.h>
+__attribute__((weak)) void f(int x) { printf("%d", x); }
+
+int
+main ()
+{
+
+ f(1);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_weak_attribute="yes"
+else
+ ac_cv_c_weak_attribute="no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_weak_attribute" >&5
+$as_echo "$ac_cv_c_weak_attribute" >&6; }
+if test $ac_cv_c_weak_attribute = yes; then
+
+$as_echo "#define HAVE_ATTR_WEAK 1" >>confdefs.h
+
+fi
+
+
if test "$srcdir" != "."; then
CPPFLAGS="$CPPFLAGS -I$srcdir"
fi
@@ -16666,7 +16719,7 @@ $as_echo "$PYTHON_CPPFLAGS" >&6; }
$as_echo_n "checking for Python library path... " >&6; }
if test -z "$PYTHON_LDFLAGS"; then
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
- print(get_config_var('BLDLIBRARY'));"`
+ print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"`
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_LDFLAGS" >&5
$as_echo "$PYTHON_LDFLAGS" >&6; }
@@ -16985,6 +17038,19 @@ if test "${with_nettle+set}" = set; then :
$as_echo "#define HAVE_NETTLE 1" >>confdefs.h
+ for ac_header in nettle/dsa-compat.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "nettle/dsa-compat.h" "ac_cv_header_nettle_dsa_compat_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_nettle_dsa_compat_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_NETTLE_DSA_COMPAT_H 1
+_ACEOF
+
+fi
+
+done
+
if test "$withval" != "" -a "$withval" != "yes"; then
CPPFLAGS="$CPPFLAGS -I$withval/include/nettle"
LDFLAGS="$LDFLAGS -L$withval/lib"
@@ -17064,8 +17130,8 @@ $as_echo "found in $ssldir" >&6; }
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_CTX_init in -lcrypto" >&5
-$as_echo_n "checking for HMAC_CTX_init in -lcrypto... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_Update in -lcrypto" >&5
+$as_echo_n "checking for HMAC_Update in -lcrypto... " >&6; }
LIBS="$LIBS -lcrypto"
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -17075,8 +17141,8 @@ int
main ()
{
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
;
return 0;
@@ -17087,7 +17153,7 @@ if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
-$as_echo "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h
+$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
else
@@ -17108,8 +17174,8 @@ int
main ()
{
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
;
return 0;
@@ -17118,7 +17184,7 @@ _ACEOF
if ac_fn_c_try_link "$LINENO"; then :
-$as_echo "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h
+$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -17140,8 +17206,8 @@ int
main ()
{
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
;
return 0;
@@ -17150,7 +17216,7 @@ _ACEOF
if ac_fn_c_try_link "$LINENO"; then :
-$as_echo "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h
+$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -17159,7 +17225,43 @@ else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- as_fn_error $? "OpenSSL found in $ssldir, but version 0.9.7 or higher is required" "$LINENO" 5
+ LIBS="$BAKLIBS"
+ LIBSSL_LIBS="$BAKSSLLIBS"
+ LIBS="$LIBS -ldl -pthread"
+ LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl -pthread" >&5
+$as_echo_n "checking if -lcrypto needs -ldl -pthread... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ int HMAC_Update(void);
+ (void)HMAC_Update();
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+
+$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "OpenSSL found in $ssldir, but version 0.9.7 or higher is required" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext \
@@ -17313,6 +17415,47 @@ fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
SSLLIB="-lssl"
+
+# check if -lcrypt32 is needed because CAPIENG needs that. (on windows)
+BAKLIBS="$LIBS"
+LIBS="-lssl $LIBS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libssl needs -lcrypt32" >&5
+$as_echo_n "checking if libssl needs -lcrypt32... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char HMAC_Update ();
+int
+main ()
+{
+return HMAC_Update ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ LIBS="$BAKLIBS"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ LIBS="$BAKLIBS"
+ LIBS="$LIBS -lcrypt32"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LibreSSL" >&5
$as_echo_n "checking for LibreSSL... " >&6; }
if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then
@@ -17378,44 +17521,49 @@ else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
-for ac_header in openssl/conf.h
+for ac_header in openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h
do :
- ac_fn_c_check_header_compile "$LINENO" "openssl/conf.h" "ac_cv_header_openssl_conf_h" "$ac_includes_default
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
"
-if test "x$ac_cv_header_openssl_conf_h" = xyes; then :
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
-#define HAVE_OPENSSL_CONF_H 1
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
-for ac_header in openssl/engine.h
+for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup
do :
- ac_fn_c_check_header_compile "$LINENO" "openssl/engine.h" "ac_cv_header_openssl_engine_h" "$ac_includes_default
-"
-if test "x$ac_cv_header_openssl_engine_h" = xyes; then :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
-#define HAVE_OPENSSL_ENGINE_H 1
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
-
done
-for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode
+
+# these check_funcs need -lssl
+BAKLIBS="$LIBS"
+LIBS="-lssl $LIBS"
+for ac_func in OPENSSL_init_ssl
do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_OPENSSL_INIT_SSL 1
_ACEOF
fi
done
+LIBS="$BAKLIBS"
+
ac_fn_c_check_decl "$LINENO" "SSL_COMP_get_compression_methods" "ac_cv_have_decl_SSL_COMP_get_compression_methods" "
$ac_includes_default
#ifdef HAVE_OPENSSL_ERR_H
@@ -17771,20 +17919,127 @@ _ACEOF
;;
esac
+# Check whether --enable-dsa was given.
+if test "${enable_dsa+set}" = set; then :
+ enableval=$enable_dsa;
+fi
+
+use_dsa="no"
+case "$enable_ecdsa" in
+ no)
+ ;;
+ *)
+ # detect if DSA is supported, and turn it off if not.
+ ac_fn_c_check_func "$LINENO" "EVP_dss1" "ac_cv_func_EVP_dss1"
+if test "x$ac_cv_func_EVP_dss1" = xyes; then :
+
+
+cat >>confdefs.h <<_ACEOF
+#define USE_DSA 1
+_ACEOF
+
+
+else
+ if test "x$enable_dsa" = "xyes"; then as_fn_error $? "OpenSSL does not support DSA and you used --enable-dsa." "$LINENO" 5
+ fi
+fi
+
+ ;;
+esac
+
+
# Check whether --enable-event-api was given.
if test "${enable_event_api+set}" = set; then :
enableval=$enable_event_api;
fi
-use_unbound_event="no"
case "$enable_event_api" in
yes)
- use_unbound_event="yes"
+ UNBOUND_EVENT_INSTALL=unbound-event-install
+
+ UNBOUND_EVENT_UNINSTALL=unbound-event-uninstall
+
;;
*)
;;
esac
+# Check whether --enable-tfo-client was given.
+if test "${enable_tfo_client+set}" = set; then :
+ enableval=$enable_tfo_client;
+fi
+
+case "$enable_tfo_client" in
+ yes)
+ case `uname` in
+ Linux) ac_fn_c_check_decl "$LINENO" "MSG_FASTOPEN" "ac_cv_have_decl_MSG_FASTOPEN" "$ac_includes_default
+#include <netinet/tcp.h>
+
+"
+if test "x$ac_cv_have_decl_MSG_FASTOPEN" = xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO" >&5
+$as_echo "$as_me: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO" >&2;}
+else
+ as_fn_error $? "TCP Fast Open is not available for client mode: please rerun without --enable-tfo-client" "$LINENO" 5
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define USE_MSG_FASTOPEN 1
+_ACEOF
+
+ ;;
+ Darwin) ac_fn_c_check_decl "$LINENO" "CONNECT_RESUME_ON_READ_WRITE" "ac_cv_have_decl_CONNECT_RESUME_ON_READ_WRITE" "$ac_includes_default
+#include <sys/socket.h>
+
+"
+if test "x$ac_cv_have_decl_CONNECT_RESUME_ON_READ_WRITE" = xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO" >&5
+$as_echo "$as_me: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO" >&2;}
+else
+ as_fn_error $? "TCP Fast Open is not available for client mode: please rerun without --enable-tfo-client" "$LINENO" 5
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define USE_OSX_MSG_FASTOPEN 1
+_ACEOF
+
+ ;;
+ esac
+ ;;
+ no|*)
+ ;;
+esac
+
+# Check whether --enable-tfo-server was given.
+if test "${enable_tfo_server+set}" = set; then :
+ enableval=$enable_tfo_server;
+fi
+
+case "$enable_tfo_server" in
+ yes)
+ ac_fn_c_check_decl "$LINENO" "TCP_FASTOPEN" "ac_cv_have_decl_TCP_FASTOPEN" "$ac_includes_default
+#include <netinet/tcp.h>
+
+"
+if test "x$ac_cv_have_decl_TCP_FASTOPEN" = xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support server mode TFO" >&5
+$as_echo "$as_me: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support server mode TFO" >&2;}
+else
+ as_fn_error $? "TCP Fast Open is not available for server mode: please rerun without --enable-tfo-server" "$LINENO" 5
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define USE_TCP_FASTOPEN 1
+_ACEOF
+
+ ;;
+ no|*)
+ ;;
+esac
+
# check for libevent
# Check whether --with-libevent was given.
@@ -18126,12 +18381,6 @@ done
if test -n "$BAK_LDFLAGS_SET"; then
LDFLAGS="$BAK_LDFLAGS"
fi
- if test "$use_unbound_event" = "yes"; then
- UNBOUND_EVENT_INSTALL=unbound-event-install
-
- UNBOUND_EVENT_UNINSTALL=unbound-event-uninstall
-
- fi
else
$as_echo "#define USE_MINI_EVENT 1" >>confdefs.h
@@ -18205,10 +18454,8 @@ if test x_$enable_static_exe = x_yes; then
staticexe="-static"
if test "$on_mingw" = yes; then
staticexe="-all-static"
- # for static crosscompile, include gdi32 and zlib here.
- if test "`uname`" = "Linux"; then
- LIBS="$LIBS -lgdi32 -lz"
- fi
+ # for static compile, include gdi32 and zlib here.
+ LIBS="$LIBS -lgdi32 -lz"
fi
fi
@@ -18653,7 +18900,7 @@ if test "$ac_res" != no; then :
fi
-for ac_func in tzset sigprocmask fcntl getpwnam getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync
+for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -19237,6 +19484,20 @@ esac
fi
+ac_fn_c_check_func "$LINENO" "strsep" "ac_cv_func_strsep"
+if test "x$ac_cv_func_strsep" = xyes; then :
+ $as_echo "#define HAVE_STRSEP 1" >>confdefs.h
+
+else
+ case " $LIBOBJS " in
+ *" strsep.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strsep.$ac_objext"
+ ;;
+esac
+
+fi
+
+
# Check whether --enable-allsymbols was given.
if test "${enable_allsymbols+set}" = set; then :
@@ -19520,6 +19781,23 @@ _ACEOF
fi
+# check for cachedb if requested
+# Check whether --enable-cachedb was given.
+if test "${enable_cachedb+set}" = set; then :
+ enableval=$enable_cachedb;
+fi
+
+case "$enable_cachedb" in
+ yes)
+
+$as_echo "#define USE_CACHEDB 1" >>confdefs.h
+
+ ;;
+ no|*)
+ # nothing
+ ;;
+esac
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if ${MAKE:-make} supports $< with implicit rule in scope" >&5
$as_echo_n "checking if ${MAKE:-make} supports $< with implicit rule in scope... " >&6; }
# on openBSD, the implicit rule make $< work.
@@ -19661,12 +19939,12 @@ _ACEOF
-version=1.5.8
+version=1.5.10
date=`date +'%b %e, %Y'`
-ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h"
+ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h contrib/libunbound.pc"
ac_config_headers="$ac_config_headers config.h"
@@ -20176,7 +20454,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by unbound $as_me 1.5.8, which was
+This file was extended by unbound $as_me 1.5.10, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20242,7 +20520,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-unbound config.status 1.5.8
+unbound config.status 1.5.10
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -20664,6 +20942,7 @@ do
"doc/unbound-host.1") CONFIG_FILES="$CONFIG_FILES doc/unbound-host.1" ;;
"smallapp/unbound-control-setup.sh") CONFIG_FILES="$CONFIG_FILES smallapp/unbound-control-setup.sh" ;;
"dnstap/dnstap_config.h") CONFIG_FILES="$CONFIG_FILES dnstap/dnstap_config.h" ;;
+ "contrib/libunbound.pc") CONFIG_FILES="$CONFIG_FILES contrib/libunbound.pc" ;;
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
diff --git a/contrib/unbound/configure.ac b/contrib/unbound/configure.ac
index 0e53a5b..fc2c676 100644
--- a/contrib/unbound/configure.ac
+++ b/contrib/unbound/configure.ac
@@ -10,14 +10,14 @@ sinclude(dnstap/dnstap.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[5])
-m4_define([VERSION_MICRO],[8])
+m4_define([VERSION_MICRO],[10])
AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl, unbound)
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=6
-LIBUNBOUND_REVISION=0
+LIBUNBOUND_REVISION=2
LIBUNBOUND_AGE=4
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -65,6 +65,8 @@ LIBUNBOUND_AGE=4
# 1.5.6 had 5:9:3
# 1.5.7 had 5:10:3
# 1.5.8 had 6:0:4 # adds ub_ctx_set_stub
+# 1.5.9 had 6:1:4
+# 1.5.10 had 6:2:4
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -106,7 +108,7 @@ esac
# are we on MinGW?
if uname -s 2>&1 | grep MINGW32 >/dev/null; then on_mingw="yes"
else
- if echo $target | grep mingw32 >/dev/null; then on_mingw="yes"
+ if echo $host $target | grep mingw32 >/dev/null; then on_mingw="yes"
else on_mingw="no"; fi
fi
@@ -116,7 +118,7 @@ fi
if test $on_mingw = "no"; then
ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"`
else
- ub_conf_file="C:\\Program Files\\Unbound\\service.conf"
+ ub_conf_file="C:\\Program Files (x86)\\Unbound\\service.conf"
fi
AC_ARG_WITH([conf_file],
AC_HELP_STRING([--with-conf-file=path],
@@ -186,7 +188,7 @@ AC_ARG_WITH(rootkey-file,
if test $on_mingw = no; then
UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key"
else
- UNBOUND_ROOTKEY_FILE="C:\\Program Files\\Unbound\\root.key"
+ UNBOUND_ROOTKEY_FILE="C:\\Program Files (x86)\\Unbound\\root.key"
fi
)
AC_SUBST(UNBOUND_ROOTKEY_FILE)
@@ -200,7 +202,7 @@ AC_ARG_WITH(rootcert-file,
if test $on_mingw = no; then
UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem"
else
- UNBOUND_ROOTCERT_FILE="C:\\Program Files\\Unbound\\icannbundle.pem"
+ UNBOUND_ROOTCERT_FILE="C:\\Program Files (x86)\\Unbound\\icannbundle.pem"
fi
)
AC_SUBST(UNBOUND_ROOTCERT_FILE)
@@ -257,6 +259,29 @@ AC_C_INLINE
ACX_CHECK_FORMAT_ATTRIBUTE
ACX_CHECK_UNUSED_ATTRIBUTE
+AC_DEFUN([CHECK_WEAK_ATTRIBUTE],
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "weak" attribute)
+AC_CACHE_VAL(ac_cv_c_weak_attribute,
+[ac_cv_c_weak_attribute=no
+AC_TRY_COMPILE(
+[ #include <stdio.h>
+__attribute__((weak)) void f(int x) { printf("%d", x); }
+], [
+ f(1);
+],
+[ac_cv_c_weak_attribute="yes"],
+[ac_cv_c_weak_attribute="no"])
+])
+
+AC_MSG_RESULT($ac_cv_c_weak_attribute)
+if test $ac_cv_c_weak_attribute = yes; then
+ AC_DEFINE(HAVE_ATTR_WEAK, 1, [Whether the C compiler accepts the "weak" attribute])
+fi
+])dnl End of CHECK_WEAK_ATTRIBUTE
+
+CHECK_WEAK_ATTRIBUTE
+
if test "$srcdir" != "."; then
CPPFLAGS="$CPPFLAGS -I$srcdir"
fi
@@ -605,6 +630,7 @@ AC_ARG_WITH([nettle], AC_HELP_STRING([--with-nettle=path],
[
USE_NETTLE="yes"
AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto])
+ AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT])
if test "$withval" != "" -a "$withval" != "yes"; then
CPPFLAGS="$CPPFLAGS -I$withval/include/nettle"
LDFLAGS="$LDFLAGS -L$withval/lib"
@@ -622,6 +648,20 @@ if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
ACX_WITH_SSL
ACX_LIB_SSL
SSLLIB="-lssl"
+
+# check if -lcrypt32 is needed because CAPIENG needs that. (on windows)
+BAKLIBS="$LIBS"
+LIBS="-lssl $LIBS"
+AC_MSG_CHECKING([if libssl needs -lcrypt32])
+AC_TRY_LINK_FUNC([HMAC_Update], [
+ AC_MSG_RESULT([no])
+ LIBS="$BAKLIBS"
+], [
+ AC_MSG_RESULT([yes])
+ LIBS="$BAKLIBS"
+ LIBS="$LIBS -lcrypt32"
+])
+
AC_MSG_CHECKING([for LibreSSL])
if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then
AC_MSG_RESULT([yes])
@@ -632,9 +672,15 @@ if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/
else
AC_MSG_RESULT([no])
fi
-AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
-AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
-AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode])
+AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h],,, [AC_INCLUDES_DEFAULT])
+AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup])
+
+# these check_funcs need -lssl
+BAKLIBS="$LIBS"
+LIBS="-lssl $LIBS"
+AC_CHECK_FUNCS([OPENSSL_init_ssl])
+LIBS="$BAKLIBS"
+
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
AC_INCLUDES_DEFAULT
#ifdef HAVE_OPENSSL_ERR_H
@@ -816,16 +862,67 @@ case "$enable_ecdsa" in
;;
esac
-AC_ARG_ENABLE(event-api, AC_HELP_STRING([--enable-event-api], [Enable (experimental) libevent-based libunbound API installed to unbound-event.h]))
-use_unbound_event="no"
+AC_ARG_ENABLE(dsa, AC_HELP_STRING([--disable-dsa], [Disable DSA support]))
+use_dsa="no"
+case "$enable_ecdsa" in
+ no)
+ ;;
+ *)
+ # detect if DSA is supported, and turn it off if not.
+ AC_CHECK_FUNC(EVP_dss1, [
+ AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
+ ], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
+ fi ])
+ ;;
+esac
+
+
+AC_ARG_ENABLE(event-api, AC_HELP_STRING([--enable-event-api], [Enable (experimental) pluggable event base libunbound API installed to unbound-event.h]))
case "$enable_event_api" in
yes)
- use_unbound_event="yes"
+ AC_SUBST(UNBOUND_EVENT_INSTALL, [unbound-event-install])
+ AC_SUBST(UNBOUND_EVENT_UNINSTALL, [unbound-event-uninstall])
;;
*)
;;
esac
+AC_ARG_ENABLE(tfo-client, AC_HELP_STRING([--enable-tfo-client], [Enable TCP Fast Open for client mode]))
+case "$enable_tfo_client" in
+ yes)
+ case `uname` in
+ Linux) AC_CHECK_DECL([MSG_FASTOPEN], [AC_MSG_WARN([Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO])],
+ [AC_MSG_ERROR([TCP Fast Open is not available for client mode: please rerun without --enable-tfo-client])],
+ [AC_INCLUDES_DEFAULT
+#include <netinet/tcp.h>
+])
+ AC_DEFINE_UNQUOTED([USE_MSG_FASTOPEN], [1], [Define this to enable client TCP Fast Open.])
+ ;;
+ Darwin) AC_CHECK_DECL([CONNECT_RESUME_ON_READ_WRITE], [AC_MSG_WARN([Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO])],
+ [AC_MSG_ERROR([TCP Fast Open is not available for client mode: please rerun without --enable-tfo-client])],
+ [AC_INCLUDES_DEFAULT
+#include <sys/socket.h>
+])
+ AC_DEFINE_UNQUOTED([USE_OSX_MSG_FASTOPEN], [1], [Define this to enable client TCP Fast Open.])
+ ;;
+ esac
+ ;;
+ no|*)
+ ;;
+esac
+
+AC_ARG_ENABLE(tfo-server, AC_HELP_STRING([--enable-tfo-server], [Enable TCP Fast Open for server mode]))
+case "$enable_tfo_server" in
+ yes)
+ AC_CHECK_DECL([TCP_FASTOPEN], [AC_MSG_WARN([Check the platform specific TFO kernel parameters are correctly configured to support server mode TFO])], [AC_MSG_ERROR([TCP Fast Open is not available for server mode: please rerun without --enable-tfo-server])], [AC_INCLUDES_DEFAULT
+#include <netinet/tcp.h>
+ ])
+ AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable server TCP Fast Open.])
+ ;;
+ no|*)
+ ;;
+esac
+
# check for libevent
AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname],
[use libevent (will check /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr or you can specify an explicit path). Slower, but allows use of large outgoing port ranges.]),
@@ -906,10 +1003,6 @@ large outgoing port ranges. ])
if test -n "$BAK_LDFLAGS_SET"; then
LDFLAGS="$BAK_LDFLAGS"
fi
- if test "$use_unbound_event" = "yes"; then
- AC_SUBST(UNBOUND_EVENT_INSTALL, [unbound-event-install])
- AC_SUBST(UNBOUND_EVENT_UNINSTALL, [unbound-event-uninstall])
- fi
else
AC_DEFINE(USE_MINI_EVENT, 1, [Define if you want to use internal select based events])
fi
@@ -950,10 +1043,8 @@ if test x_$enable_static_exe = x_yes; then
staticexe="-static"
if test "$on_mingw" = yes; then
staticexe="-all-static"
- # for static crosscompile, include gdi32 and zlib here.
- if test "`uname`" = "Linux"; then
- LIBS="$LIBS -lgdi32 -lz"
- fi
+ # for static compile, include gdi32 and zlib here.
+ LIBS="$LIBS -lgdi32 -lz"
fi
fi
@@ -1047,7 +1138,7 @@ AC_INCLUDES_DEFAULT
#endif
])
AC_SEARCH_LIBS([setusercontext], [util])
-AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync])
+AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync])
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
@@ -1140,6 +1231,7 @@ fi
LIBOBJ_WITHOUT_CTIME="$LIBOBJS"
AC_SUBST(LIBOBJ_WITHOUT_CTIME)
AC_REPLACE_FUNCS(ctime_r)
+AC_REPLACE_FUNCS(strsep)
AC_ARG_ENABLE(allsymbols, AC_HELP_STRING([--enable-allsymbols], [export all symbols from libunbound and link binaries to it, smaller install size but libunbound export table is polluted by internal symbols]))
case "$enable_allsymbols" in
@@ -1192,6 +1284,17 @@ dt_DNSTAP([$UNBOUND_RUN_DIR/dnstap.sock],
]
)
+# check for cachedb if requested
+AC_ARG_ENABLE(cachedb, AC_HELP_STRING([--enable-cachedb], [enable cachedb module that can use external cache storage]))
+case "$enable_cachedb" in
+ yes)
+ AC_DEFINE([USE_CACHEDB], [1], [Define to 1 to use cachedb support])
+ ;;
+ no|*)
+ # nothing
+ ;;
+esac
+
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
# on openBSD, the implicit rule make $< work.
# on Solaris, it does not work ($? is changed sources, $^ lists dependencies).
@@ -1358,6 +1461,11 @@ AHX_MEMCMP_BROKEN(unbound)
char *ctime_r(const time_t *timep, char *buf);
#endif
+#ifndef HAVE_STRSEP
+#define strsep unbound_strsep
+char *strsep(char **stringp, const char *delim);
+#endif
+
#ifndef HAVE_ISBLANK
#define isblank unbound_isblank
int isblank(int c);
@@ -1471,6 +1579,6 @@ dnl if this is a distro tarball, that was already done by makedist.sh
AC_SUBST(version, [VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO])
AC_SUBST(date, [`date +'%b %e, %Y'`])
-AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h])
+AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h contrib/libunbound.pc])
AC_CONFIG_HEADER([config.h])
AC_OUTPUT
diff --git a/contrib/unbound/contrib/README b/contrib/unbound/contrib/README
new file mode 100644
index 0000000..8eae9b5
--- /dev/null
+++ b/contrib/unbound/contrib/README
@@ -0,0 +1,31 @@
+These files are contributed to unbound, and are not part of the official
+distribution but may be helpful.
+
+* rc_d_unbound: FreeBSD compatible /etc/rc.d script.
+* parseunbound.pl: perl script to run from cron that parses statistics from
+ the log file and stores them.
+* unbound.spec and unbound.init: RPM specfile and Linux rc.d initfile.
+* update-anchor.sh: shell script that uses unbound-host to update a set
+ of trust anchor files. Run from cron twice a month.
+* unbound_munin_ : plugin for munin statistics report
+* unbound_cacti.tar.gz : setup files for cacti statistics report
+* selinux: the .fc and .te files for SElinux protection of the unbound daemon
+* unbound.plist: launchd configuration file for MacOSX.
+* build-unbound-localzone-from-hosts.pl: perl script to turn /etc/hosts into
+ a local-zone and local-data include file for unbound.conf.
+* unbound-host.nagios.patch: makes unbound-host return status that fits right
+ in with the nagios monitoring framework. Contributed by Migiel de Vos.
+* patch_rsamd5_enable.diff: this patch enables RSAMD5 validation (otherwise
+ it is treated as insecure). The RSAMD5 algorithm is deprecated (RFC6725).
+* create_unbound_ad_servers.sh: shell script to enter anti-ad server lists.
+* create_unbound_ad_servers.cmd: windows script to enter anti-ad server lists.
+* unbound_cache.sh: shell script to save and load the cache.
+* unbound_cache.cmd: windows script to save and load the cache.
+* warmup.sh: shell script to warm up DNS cache by your own MRU domains.
+* warmup.cmd: windows script to warm up DNS cache by your own MRU domains.
+* aaaa-filter-iterator.patch: adds config option aaaa-filter: yes that
+ works like the BIND feature (removes AAAA records unless AAAA-only domain).
+ Useful for certain 'broken IPv6 default route' scenarios.
+ Patch from Stephane Lapie for ASAHI Net.
+* unbound_smf22.tar.gz: Solaris SMF installation/removal scripts.
+ Contributed by Yuri Voinov.
diff --git a/contrib/unbound/contrib/aaaa-filter-iterator.patch b/contrib/unbound/contrib/aaaa-filter-iterator.patch
new file mode 100644
index 0000000..0647f49
--- /dev/null
+++ b/contrib/unbound/contrib/aaaa-filter-iterator.patch
@@ -0,0 +1,413 @@
+Index: trunk/doc/unbound.conf.5.in
+===================================================================
+--- trunk/doc/unbound.conf.5.in (revision 3587)
++++ trunk/doc/unbound.conf.5.in (working copy)
+@@ -593,6 +593,13 @@
+ possible. Best effort approach, full QNAME and original QTYPE will be sent when
+ upstream replies with a RCODE other than NOERROR. Default is off.
+ .TP
++.B aaaa\-filter: \fI<yes or no>
++Activate behavior similar to BIND's AAAA-filter.
++This forces the dropping of all AAAA records, unless in the case of
++explicit AAAA queries, when no A records have been confirmed.
++This also causes an additional A query to be sent for each AAAA query.
++This breaks DNSSEC!
++.TP
+ .B private\-address: \fI<IP address or subnet>
+ Give IPv4 of IPv6 addresses or classless subnets. These are addresses
+ on your private network, and are not allowed to be returned for
+Index: trunk/iterator/iter_scrub.c
+===================================================================
+--- trunk/iterator/iter_scrub.c (revision 3587)
++++ trunk/iterator/iter_scrub.c (working copy)
+@@ -617,6 +617,32 @@
+ }
+
+ /**
++ * ASN: Lookup A records from rrset cache.
++ * @param qinfo: the question originally asked.
++ * @param env: module environment with config and cache.
++ * @param ie: iterator environment with private address data.
++ * @return 0 if no A record found, 1 if A record found.
++ */
++static int
++asn_lookup_a_record_from_cache(struct query_info* qinfo,
++ struct module_env* env, struct iter_env* ATTR_UNUSED(ie))
++{
++ struct ub_packed_rrset_key* akey;
++
++ /* get cached A records for queried name */
++ akey = rrset_cache_lookup(env->rrset_cache, qinfo->qname,
++ qinfo->qname_len, LDNS_RR_TYPE_A, qinfo->qclass,
++ 0, *env->now, 0);
++ if(akey) { /* we had some. */
++ log_rrset_key(VERB_ALGO, "ASN-AAAA-filter: found A record",
++ akey);
++ lock_rw_unlock(&akey->entry.lock);
++ return 1;
++ }
++ return 0;
++}
++
++/**
+ * Given a response event, remove suspect RRsets from the response.
+ * "Suspect" rrsets are potentially poison. Note that this routine expects
+ * the response to be in a "normalized" state -- that is, all "irrelevant"
+@@ -635,6 +661,7 @@
+ struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
+ struct iter_env* ie)
+ {
++ int found_a_record = 0; /* ASN: do we have a A record? */
+ int del_addi = 0; /* if additional-holding rrsets are deleted, we
+ do not trust the normalized additional-A-AAAA any more */
+ struct rrset_parse* rrset, *prev;
+@@ -670,6 +697,13 @@
+ rrset = rrset->rrset_all_next;
+ }
+
++ /* ASN: Locate any A record we can find */
++ if((ie->aaaa_filter) && (qinfo->qtype == LDNS_RR_TYPE_AAAA)) {
++ found_a_record = asn_lookup_a_record_from_cache(qinfo,
++ env, ie);
++ }
++ /* ASN: End of added code */
++
+ /* At this point, we brutally remove ALL rrsets that aren't
+ * children of the originating zone. The idea here is that,
+ * as far as we know, the server that we contacted is ONLY
+@@ -681,6 +715,24 @@
+ rrset = msg->rrset_first;
+ while(rrset) {
+
++ /* ASN: For AAAA records only... */
++ if((ie->aaaa_filter) && (rrset->type == LDNS_RR_TYPE_AAAA)) {
++ /* ASN: If this is not a AAAA query, then remove AAAA
++ * records, no questions asked. If this IS a AAAA query
++ * then remove AAAA records if we have an A record.
++ * Otherwise, leave things be. */
++ if((qinfo->qtype != LDNS_RR_TYPE_AAAA) ||
++ (found_a_record)) {
++ remove_rrset("ASN-AAAA-filter: removing AAAA "
++ "for record", pkt, msg, prev, &rrset);
++ continue;
++ }
++ log_nametypeclass(VERB_ALGO, "ASN-AAAA-filter: "
++ "keep AAAA for", zonename,
++ LDNS_RR_TYPE_AAAA, qinfo->qclass);
++ }
++ /* ASN: End of added code */
++
+ /* remove private addresses */
+ if( (rrset->type == LDNS_RR_TYPE_A ||
+ rrset->type == LDNS_RR_TYPE_AAAA)) {
+Index: trunk/iterator/iter_utils.c
+===================================================================
+--- trunk/iterator/iter_utils.c (revision 3587)
++++ trunk/iterator/iter_utils.c (working copy)
+@@ -175,6 +175,7 @@
+ }
+ iter_env->supports_ipv6 = cfg->do_ip6;
+ iter_env->supports_ipv4 = cfg->do_ip4;
++ iter_env->aaaa_filter = cfg->aaaa_filter;
+ return 1;
+ }
+
+Index: trunk/iterator/iterator.c
+===================================================================
+--- trunk/iterator/iterator.c (revision 3587)
++++ trunk/iterator/iterator.c (working copy)
+@@ -1776,6 +1776,53 @@
+
+ return 0;
+ }
++
++/**
++ * ASN: This event state was added as an intermediary step between
++ * QUERYTARGETS_STATE and the next step, in order to cast a subquery for the
++ * purpose of caching A records for the queried name.
++ *
++ * @param qstate: query state.
++ * @param iq: iterator query state.
++ * @param ie: iterator shared global environment.
++ * @param id: module id.
++ * @return true if the event requires more request processing immediately,
++ * false if not. This state only returns true when it is generating
++ * a SERVFAIL response because the query has hit a dead end.
++ */
++static int
++asn_processQueryAAAA(struct module_qstate* qstate, struct iter_qstate* iq,
++ struct iter_env* ATTR_UNUSED(ie), int id)
++{
++ struct module_qstate* subq = NULL;
++
++ log_assert(iq->fetch_a_for_aaaa == 0);
++
++ /* flag the query properly in order to not loop */
++ iq->fetch_a_for_aaaa = 1;
++
++ /* re-throw same query, but with a different type */
++ if(!generate_sub_request(iq->qchase.qname,
++ iq->qchase.qname_len, LDNS_RR_TYPE_A,
++ iq->qchase.qclass, qstate, id, iq,
++ INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
++ log_nametypeclass(VERB_ALGO, "ASN-AAAA-filter: failed "
++ "preloading of A record for",
++ iq->qchase.qname, LDNS_RR_TYPE_A,
++ iq->qchase.qclass);
++ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
++ }
++ log_nametypeclass(VERB_ALGO, "ASN-AAAA-filter: "
++ "preloading records in cache for",
++ iq->qchase.qname, LDNS_RR_TYPE_A,
++ iq->qchase.qclass);
++
++ /* set this query as waiting */
++ qstate->ext_state[id] = module_wait_subquery;
++ /* at this point break loop */
++ return 0;
++}
++/* ASN: End of added code */
+
+ /**
+ * This is the request event state where the request will be sent to one of
+@@ -1823,6 +1870,13 @@
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
+
++ /* ASN: If we have a AAAA query, then also query for A records */
++ if((ie->aaaa_filter) && (iq->qchase.qtype == LDNS_RR_TYPE_AAAA) &&
++ (iq->fetch_a_for_aaaa == 0)) {
++ return next_state(iq, ASN_FETCH_A_FOR_AAAA_STATE);
++ }
++ /* ASN: End of added code */
++
+ /* Make sure we have a delegation point, otherwise priming failed
+ * or another failure occurred */
+ if(!iq->dp) {
+@@ -2922,6 +2976,61 @@
+ return 0;
+ }
+
++/**
++ * ASN: Do final processing on responses to A queries originated from AAAA
++ * queries. Events reach this state after the iterative resolution algorithm
++ * terminates.
++ * This is required down the road to decide whether to scrub AAAA records
++ * from the results or not.
++ *
++ * @param qstate: query state.
++ * @param id: module id.
++ * @param forq: super query state.
++ */
++static void
++asn_processAAAAResponse(struct module_qstate* qstate, int id,
++ struct module_qstate* super)
++{
++ /*struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];*/
++ struct iter_qstate* super_iq = (struct iter_qstate*)super->minfo[id];
++ struct delegpt_ns* dpns = NULL;
++ int error = (qstate->return_rcode != LDNS_RCODE_NOERROR);
++
++ log_assert(super_iq->fetch_a_for_aaaa > 0);
++
++ /* let super go to evaluation of targets after this */
++ super_iq->state = QUERYTARGETS_STATE;
++
++ log_query_info(VERB_ALGO, "ASN-AAAA-filter: processAAAAResponse",
++ &qstate->qinfo);
++ log_query_info(VERB_ALGO, "ASN-AAAA-filter: processAAAAResponse super",
++ &super->qinfo);
++
++ if(super_iq->dp)
++ dpns = delegpt_find_ns(super_iq->dp,
++ qstate->qinfo.qname, qstate->qinfo.qname_len);
++ if (!dpns) {
++ /* not interested */
++ verbose(VERB_ALGO, "ASN-AAAA-filter: subq: %s, but parent not "
++ "interested%s", (error ? "error, but" : "success"),
++ (super_iq->dp ? "anymore" : " (was reset)"));
++ log_query_info(VERB_ALGO, "ASN-AAAA-filter: superq", &super->qinfo);
++ if(super_iq->dp && error)
++ delegpt_log(VERB_ALGO, super_iq->dp);
++ return;
++ } else if (error) {
++ verbose(VERB_ALGO, "ASN-AAAA-filter: mark as failed, "
++ "and go to target query.");
++ /* see if the failure did get (parent-lame) info */
++ if(!cache_fill_missing(super->env,
++ super_iq->qchase.qclass, super->region,
++ super_iq->dp))
++ log_err("ASN-AAAA-filter: out of memory adding missing");
++ dpns->resolved = 1; /* mark as failed */
++ }
++}
++/* ASN: End of added code */
++
+ /*
+ * Return priming query results to interestes super querystates.
+ *
+@@ -2941,6 +3050,9 @@
+ else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
+ super->minfo[id])->state == DSNS_FIND_STATE)
+ processDSNSResponse(qstate, id, super);
++ else if (super->qinfo.qtype == LDNS_RR_TYPE_AAAA && ((struct iter_qstate*)
++ super->minfo[id])->state == ASN_FETCH_A_FOR_AAAA_STATE)
++ asn_processAAAAResponse(qstate, id, super);
+ else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
+ error_supers(qstate, id, super);
+ else if(qstate->is_priming)
+@@ -2978,6 +3090,9 @@
+ case INIT_REQUEST_3_STATE:
+ cont = processInitRequest3(qstate, iq, id);
+ break;
++ case ASN_FETCH_A_FOR_AAAA_STATE:
++ cont = asn_processQueryAAAA(qstate, iq, ie, id);
++ break;
+ case QUERYTARGETS_STATE:
+ cont = processQueryTargets(qstate, iq, ie, id);
+ break;
+@@ -3270,6 +3385,8 @@
+ return "INIT REQUEST STATE (stage 2)";
+ case INIT_REQUEST_3_STATE:
+ return "INIT REQUEST STATE (stage 3)";
++ case ASN_FETCH_A_FOR_AAAA_STATE:
++ return "ASN_FETCH_A_FOR_AAAA_STATE";
+ case QUERYTARGETS_STATE :
+ return "QUERY TARGETS STATE";
+ case PRIME_RESP_STATE :
+@@ -3294,6 +3411,7 @@
+ case INIT_REQUEST_STATE :
+ case INIT_REQUEST_2_STATE :
+ case INIT_REQUEST_3_STATE :
++ case ASN_FETCH_A_FOR_AAAA_STATE :
+ case QUERYTARGETS_STATE :
+ case COLLECT_CLASS_STATE :
+ return 0;
+Index: trunk/iterator/iterator.h
+===================================================================
+--- trunk/iterator/iterator.h (revision 3587)
++++ trunk/iterator/iterator.h (working copy)
+@@ -113,6 +113,9 @@
+ */
+ int* target_fetch_policy;
+
++ /** ASN: AAAA-filter flag */
++ int aaaa_filter;
++
+ /** ip6.arpa dname in wireformat, used for qname-minimisation */
+ uint8_t* ip6arpa_dname;
+ };
+@@ -163,6 +166,14 @@
+ INIT_REQUEST_3_STATE,
+
+ /**
++ * This state is responsible for intercepting AAAA queries,
++ * and launch a A subquery on the same target, to populate the
++ * cache with A records, so the AAAA filter scrubbing logic can
++ * work.
++ */
++ ASN_FETCH_A_FOR_AAAA_STATE,
++
++ /**
+ * Each time a delegation point changes for a given query or a
+ * query times out and/or wakes up, this state is (re)visited.
+ * This state is reponsible for iterating through a list of
+@@ -346,6 +357,13 @@
+ */
+ int refetch_glue;
+
++ /**
++ * ASN: This is a flag that, if true, means that this query is
++ * for fetching A records to populate cache and determine if we must
++ * return AAAA records or not.
++ */
++ int fetch_a_for_aaaa;
++
+ /** list of pending queries to authoritative servers. */
+ struct outbound_list outlist;
+
+Index: trunk/pythonmod/interface.i
+===================================================================
+--- trunk/pythonmod/interface.i (revision 3587)
++++ trunk/pythonmod/interface.i (working copy)
+@@ -632,6 +632,7 @@
+ int harden_dnssec_stripped;
+ int harden_referral_path;
+ int use_caps_bits_for_id;
++ int aaaa_filter; /* ASN */
+ struct config_strlist* private_address;
+ struct config_strlist* private_domain;
+ size_t unwanted_threshold;
+Index: trunk/util/config_file.c
+===================================================================
+--- trunk/util/config_file.c (revision 3587)
++++ trunk/util/config_file.c (working copy)
+@@ -176,6 +176,7 @@
+ cfg->harden_referral_path = 0;
+ cfg->harden_algo_downgrade = 0;
+ cfg->use_caps_bits_for_id = 0;
++ cfg->aaaa_filter = 0; /* ASN: default is disabled */
+ cfg->caps_whitelist = NULL;
+ cfg->private_address = NULL;
+ cfg->private_domain = NULL;
+Index: trunk/util/config_file.h
+===================================================================
+--- trunk/util/config_file.h (revision 3587)
++++ trunk/util/config_file.h (working copy)
+@@ -179,6 +179,8 @@
+ int harden_algo_downgrade;
+ /** use 0x20 bits in query as random ID bits */
+ int use_caps_bits_for_id;
++ /** ASN: enable AAAA filter? */
++ int aaaa_filter;
+ /** 0x20 whitelist, domains that do not use capsforid */
+ struct config_strlist* caps_whitelist;
+ /** strip away these private addrs from answers, no DNS Rebinding */
+Index: trunk/util/configlexer.lex
+===================================================================
+--- trunk/util/configlexer.lex (revision 3587)
++++ trunk/util/configlexer.lex (working copy)
+@@ -267,6 +267,7 @@
+ use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
+ caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
+ unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
++aaaa-filter{COLON} { YDVAR(1, VAR_AAAA_FILTER) }
+ private-address{COLON} { YDVAR(1, VAR_PRIVATE_ADDRESS) }
+ private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
+ prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
+Index: trunk/util/configparser.y
+===================================================================
+--- trunk/util/configparser.y (revision 3587)
++++ trunk/util/configparser.y (working copy)
+@@ -92,6 +92,7 @@
+ %token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
+ %token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR
+ %token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS
++%token VAR_AAAA_FILTER
+ %token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
+ %token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
+ %token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
+@@ -169,6 +170,7 @@
+ server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
+ server_harden_referral_path | server_private_address |
+ server_private_domain | server_extended_statistics |
++ server_aaaa_filter |
+ server_local_data_ptr | server_jostle_timeout |
+ server_unwanted_reply_threshold | server_log_time_ascii |
+ server_domain_insecure | server_val_sig_skew_min |
+@@ -893,6 +895,15 @@
+ yyerror("out of memory");
+ }
+ ;
++server_aaaa_filter: VAR_AAAA_FILTER STRING_ARG
++ {
++ OUTYY(("P(server_aaaa_filter:%s)\n", $2));
++ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
++ yyerror("expected yes or no.");
++ else cfg_parser->cfg->aaaa_filter = (strcmp($2, "yes")==0);
++ free($2);
++ }
++ ;
+ server_private_address: VAR_PRIVATE_ADDRESS STRING_ARG
+ {
+ OUTYY(("P(server_private_address:%s)\n", $2));
diff --git a/contrib/unbound/contrib/build-unbound-localzone-from-hosts.pl b/contrib/unbound/contrib/build-unbound-localzone-from-hosts.pl
new file mode 100755
index 0000000..c11bbc3
--- /dev/null
+++ b/contrib/unbound/contrib/build-unbound-localzone-from-hosts.pl
@@ -0,0 +1,67 @@
+#!/usr/bin/perl -WT
+
+use strict;
+use warnings;
+
+my $hostsfile = '/etc/hosts';
+my $localzonefile = '/etc/unbound/localzone.conf.new';
+
+my $localzone = 'example.com';
+
+open( HOSTS,"<${hostsfile}" ) or die( "Could not open ${hostsfile}: $!" );
+open( ZONE,">${localzonefile}" ) or die( "Could not open ${localzonefile}: $!" );
+
+print ZONE "server:\n\n";
+print ZONE "local-zone: \"${localzone}\" transparent\n\n";
+
+my %ptrhash;
+
+while ( my $hostline = <HOSTS> ) {
+
+ # Skip comments
+ if ( $hostline !~ "^#" and $hostline !~ '^\s+$' ) {
+
+ my @entries = split( /\s+/, $hostline );
+
+ my $ip;
+
+ my $count = 0;
+ foreach my $entry ( @entries ) {
+ if ( $count == 0 ) {
+ $ip = $entry;
+ } else {
+
+ if ( $count == 1) {
+
+ # Only return localhost for 127.0.0.1 and ::1
+ if ( ($ip ne '127.0.0.1' and $ip ne '::1') or $entry =~ 'localhost' ) {
+ if ( ! defined $ptrhash{$ip} ) {
+ $ptrhash{$ip} = $entry;
+ print ZONE "local-data-ptr: \"$ip $entry\"\n";
+ }
+ }
+
+ }
+
+ # Use AAAA for IPv6 addresses
+ my $a = 'A';
+ if ( $ip =~ ':' ) {
+ $a = 'AAAA';
+ }
+
+ print ZONE "local-data: \"$entry ${a} $ip\"\n";
+
+ }
+ $count++;
+ }
+ print ZONE "\n";
+
+
+ }
+}
+
+
+
+
+__END__
+
diff --git a/contrib/unbound/contrib/create_unbound_ad_servers.cmd b/contrib/unbound/contrib/create_unbound_ad_servers.cmd
new file mode 100644
index 0000000..91d18db
--- /dev/null
+++ b/contrib/unbound/contrib/create_unbound_ad_servers.cmd
@@ -0,0 +1,33 @@
+@Echo off
+rem Convert the Yoyo.org anti-ad server listing
+rem into an unbound dns spoof redirection list.
+rem Written by Y.Voinov (c) 2014
+
+rem Note: Wget required!
+
+rem Variables
+set prefix="C:\Program Files (x86)"
+set dst_dir=%prefix%\Unbound
+set work_dir=%TEMP%
+set list_addr="http://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=1&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D="
+
+rem Check Wget installed
+for /f "delims=" %%a in ('where wget') do @set wget=%%a
+if /I "%wget%"=="" echo Wget not found. If installed, add path to PATH environment variable. & exit 1
+echo Wget found: %wget%
+
+"%wget%" -O %work_dir%\yoyo_ad_servers %list_addr%
+
+del /Q /F /S %dst_dir%\unbound_ad_servers
+
+for /F "eol=; tokens=*" %%a in (%work_dir%\yoyo_ad_servers) do (
+echo local-zone: %%a redirect>>%dst_dir%\unbound_ad_servers
+echo local-data: "%%a A 127.0.0.1">>%dst_dir%\unbound_ad_servers
+)
+
+echo Done.
+rem then add an include line to your unbound.conf pointing to the full path of
+rem the unbound_ad_servers file:
+rem
+rem include: $dst_dir/unbound_ad_servers
+rem
diff --git a/contrib/unbound/contrib/create_unbound_ad_servers.sh b/contrib/unbound/contrib/create_unbound_ad_servers.sh
new file mode 100755
index 0000000..d31f078b
--- /dev/null
+++ b/contrib/unbound/contrib/create_unbound_ad_servers.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# Convert the Yoyo.org anti-ad server listing
+# into an unbound dns spoof redirection list.
+# Modified by Y.Voinov (c) 2014
+
+# Note: Wget required!
+
+# Variables
+dst_dir="/etc/opt/csw/unbound"
+work_dir="/tmp"
+list_addr="http://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=1&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D="
+
+# OS commands
+CAT=`which cat`
+ECHO=`which echo`
+WGET=`which wget`
+
+# Check Wget installed
+if [ ! -f $WGET ]; then
+ echo "Wget not found. Exiting..."
+ exit 1
+fi
+
+$WGET -O $work_dir/yoyo_ad_servers "$list_addr" && \
+$CAT $work_dir/yoyo_ad_servers | \
+while read line ; \
+ do \
+ $ECHO "local-zone: \"$line\" redirect" ;\
+ $ECHO "local-data: \"$line A 127.0.0.1\"" ;\
+ done > \
+$dst_dir/unbound_ad_servers
+
+echo "Done."
+# then add an include line to your unbound.conf pointing to the full path of
+# the unbound_ad_servers file:
+#
+# include: $dst_dir/unbound_ad_servers
+# \ No newline at end of file
diff --git a/contrib/unbound/contrib/libunbound.pc.in b/contrib/unbound/contrib/libunbound.pc.in
new file mode 100644
index 0000000..c0d1286
--- /dev/null
+++ b/contrib/unbound/contrib/libunbound.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: unbound
+Description: Library with validating, recursive, and caching DNS resolver
+URL: http://www.unbound.net
+Version: @PACKAGE_VERSION@
+Requires:
+Libs: -L${libdir} -lunbound @SSLLIB@ @LIBS@
+Libs.private: @LDFLAGS@
+Cflags: -I${includedir}
diff --git a/contrib/unbound/contrib/parseunbound.pl b/contrib/unbound/contrib/parseunbound.pl
new file mode 100755
index 0000000..6a6a76d
--- /dev/null
+++ b/contrib/unbound/contrib/parseunbound.pl
@@ -0,0 +1,140 @@
+#!/usr/local/bin/perl -w
+#
+# Script to parse the output from the unbound namedaemon.
+# Unbound supports a threading model, and outputs a multiline log-blob for
+# every thread.
+#
+# This script should parse all threads of the once, and store it
+# in a local cached file for speedy results when queried lots.
+#
+use strict;
+use POSIX qw(SEEK_END);
+use Storable;
+use FileHandle;
+use Carp qw(croak carp);
+use constant UNBOUND_CACHE => "/var/tmp/unbound-cache.stor";
+
+my $run_from_cron = @ARGV && $ARGV[0] eq "--cron" && shift;
+my $DEBUG = -t STDERR;
+
+# NB. VERY IMPORTANTES: set this when running this script.
+my $numthreads = 4;
+
+### if cache exists, read it in. and is newer than 3 minutes
+if ( -r UNBOUND_CACHE ) {
+ my $result = retrieve(UNBOUND_CACHE);
+ if (-M _ < 3/24/60 && !$run_from_cron ) {
+ print STDERR "Cached results:\n" if $DEBUG;
+ print join("\n", @$result), "\n";
+ exit;
+ }
+}
+my $logfile = shift or die "Usage: parseunbound.pl --cron unboundlogfile";
+my $in = new FileHandle $logfile or die "Cannot open $logfile: $!\n";
+
+# there is a special key 'thread' that indicates the thread. its not used, but returned anyway.
+my @records = ('thread', 'queries', 'cachehits', 'recursions', 'recursionavg',
+ 'outstandingmax', 'outstandingavg', 'outstandingexc',
+ 'median25', 'median50', 'median75',
+ 'us_0', 'us_1', 'us_2', 'us_4', 'us_8', 'us_16', 'us_32',
+ 'us_64', 'us_128', 'us_256', 'us_512', 'us_1024', 'us_2048',
+ 'us_4096', 'us_8192', 'us_16384', 'us_32768', 'us_65536',
+ 'us_131072', 'us_262144', 'us_524288', 's_1', 's_2', 's_4',
+ 's_8', 's_16', 's_32', 's_64', 's_128', 's_256', 's_512');
+# Stats hash containing one or more keys. for every thread, 1 key.
+my %allstats = (); # key="$threadid", stats={key => value}
+my %startstats = (); # when we got a queries entry for this thread
+my %donestats = (); # same, but only when we got a histogram entry for it
+# stats hash contains name/value pairs of the actual numbers for that thread.
+my $offset = 0;
+my $inthread=0;
+my $inpid;
+
+# We should continue looping untill we meet these conditions:
+# a) more total queries than the previous run (which defaults to 0) AND
+# b) parsed all $numthreads threads in the log.
+my $numqueries = $previousresult ? $previousresult->[1] : 0;
+
+# Main loop
+while ( scalar keys %startstats < $numthreads || scalar keys %donestats < $numthreads) {
+ $offset += 10000;
+ if ( $offset > -s $logfile or $offset > 10_000_000 ) {
+ die "Cannot find stats in $logfile\n";
+ }
+ $in->seek(-$offset, SEEK_END) or croak "cannot seek $logfile: $!\n";
+
+ for my $line ( <$in> ) {
+ chomp($line);
+
+ #[1208777234] unbound[6705:0]
+ if ($line =~ m/^\[\d+\] unbound\[\d+:(\d+)\]/) {
+ $inthread = $1;
+ if ($inthread + 1 > $numthreads) {
+ die "Hey. lazy. change \$numthreads in this script to ($inthread)\n";
+ }
+ }
+ # this line doesn't contain a pid:thread. skip.
+ else {
+ next;
+ }
+
+ if ( $line =~ m/info: server stats for thread \d+: (\d+) queries, (\d+) answers from cache, (\d+) recursions/ ) {
+ $startstats{$inthread} = 1;
+ $allstats{$inthread}->{thread} = $inthread;
+ $allstats{$inthread}->{queries} = $1;
+ $allstats{$inthread}->{cachehits} = $2;
+ $allstats{$inthread}->{recursions} = $3;
+ }
+ elsif ( $line =~ m/info: server stats for thread (\d+): requestlist max (\d+) avg ([0-9\.]+) exceeded (\d+)/ ) {
+ $allstats{$inthread}->{outstandingmax} = $2;
+ $allstats{$inthread}->{outstandingavg} = int($3); # This is a float; rrdtool only handles ints.
+ $allstats{$inthread}->{outstandingexc} = $4;
+ }
+ elsif ( $line =~ m/info: average recursion processing time ([0-9\.]+) sec/ ) {
+ $allstats{$inthread}->{recursionavg} = int($1 * 1000); # change sec to milisec.
+ }
+ elsif ( $line =~ m/info: histogram of recursion processing times/ ) {
+ next;
+ }
+ elsif ( $line =~ m/info: \[25%\]=([0-9\.]+) median\[50%\]=([0-9\.]+) \[75%\]=([0-9\.]+)/ ) {
+ $allstats{$inthread}->{median25} = int($1 * 1000000); # change seconds to usec
+ $allstats{$inthread}->{median50} = int($2 * 1000000);
+ $allstats{$inthread}->{median75} = int($3 * 1000000);
+ }
+ elsif ( $line =~ m/info: lower\(secs\) upper\(secs\) recursions/ ) {
+ # since after this line we're unsure if we get these numbers
+ # at all, we sould consider this marker as the end of the
+ # block. Chances that we're parsing a file halfway written
+ # at this stage are small. Bold statement.
+ $donestats{$inthread} = 1;
+ next;
+ }
+ elsif ( $line =~ m/info:\s+(\d+)\.(\d+)\s+(\d+)\.(\d+)\s+(\d+)/ ) {
+ my ($froms, $fromus, $toms, $tous, $counter) = ($1, $2, $3, $4, $5);
+ my $prefix = '';
+ if ($froms > 0) {
+ $allstats{$inthread}->{'s_' . int($froms)} = $counter;
+ } else {
+ $allstats{$inthread}->{'us_' . int($fromus)} = $counter;
+ }
+ }
+ }
+}
+
+my @result;
+# loop on the records we want to store
+for my $key ( @records ) {
+ my $sum = 0;
+ # these are the different threads parsed
+ foreach my $thread ( 0 .. $numthreads - 1 ) {
+ $sum += ($allstats{$thread}->{$key} || 0);
+ }
+ print STDERR "$key = " . $sum . "\n" if $DEBUG;
+ push @result, $sum;
+}
+print join("\n", @result), "\n";
+store \@result, UNBOUND_CACHE;
+
+if ($DEBUG) {
+ print STDERR "Threads: " . (scalar keys %allstats) . "\n";
+}
diff --git a/contrib/unbound/contrib/patch_rsamd5_enable.diff b/contrib/unbound/contrib/patch_rsamd5_enable.diff
new file mode 100644
index 0000000..dfd4a7b
--- /dev/null
+++ b/contrib/unbound/contrib/patch_rsamd5_enable.diff
@@ -0,0 +1,22 @@
+Index: validator/val_secalgo.c
+===================================================================
+--- validator/val_secalgo.c (revision 2759)
++++ validator/val_secalgo.c (working copy)
+@@ -153,7 +153,7 @@
+ switch(id) {
+ case LDNS_RSAMD5:
+ /* RFC 6725 deprecates RSAMD5 */
+- return 0;
++ return 1;
+ case LDNS_DSA:
+ case LDNS_DSA_NSEC3:
+ case LDNS_RSASHA1:
+@@ -617,7 +617,7 @@
+ switch(id) {
+ case LDNS_RSAMD5:
+ /* RFC 6725 deprecates RSAMD5 */
+- return 0;
++ return 1;
+ case LDNS_DSA:
+ case LDNS_DSA_NSEC3:
+ case LDNS_RSASHA1:
diff --git a/contrib/unbound/contrib/rc_d_unbound b/contrib/unbound/contrib/rc_d_unbound
new file mode 100755
index 0000000..5651614
--- /dev/null
+++ b/contrib/unbound/contrib/rc_d_unbound
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# unbound freebsd startup rc.d script, modified from the named script.
+# uses the default unbound installation path and pidfile location.
+# copy this to /etc/rc.d/unbound
+# and put unbound_enable="YES" into rc.conf
+#
+
+# PROVIDE: unbound
+# REQUIRE: SERVERS cleanvar
+# KEYWORD: shutdown
+
+. /etc/rc.subr
+
+name="unbound"
+rcvar=`set_rcvar`
+
+load_rc_config $name
+
+command="/usr/local/sbin/unbound"
+pidfile=${unbound_pidfile:-"/usr/local/etc/unbound/unbound.pid"}
+command_args=${unbound_flags:-"-c /usr/local/etc/unbound/unbound.conf"}
+extra_commands="reload"
+
+run_rc_command "$1"
diff --git a/contrib/unbound/contrib/selinux/unbound.fc b/contrib/unbound/contrib/selinux/unbound.fc
new file mode 100644
index 0000000..f7e63ea
--- /dev/null
+++ b/contrib/unbound/contrib/selinux/unbound.fc
@@ -0,0 +1,4 @@
+/etc/unbound(/.*)? system_u:object_r:unbound_conf_t:s0
+/etc/rc\.d/init\.d/unbound -- system_u:object_r:unbound_initrc_exec_t:s0
+/usr/sbin/unbound -- system_u:object_r:unbound_exec_t:s0
+/var/run/unbound(/.*)? system_u:object_r:unbound_var_run_t:s0
diff --git a/contrib/unbound/contrib/selinux/unbound.te b/contrib/unbound/contrib/selinux/unbound.te
new file mode 100644
index 0000000..d407ed3
--- /dev/null
+++ b/contrib/unbound/contrib/selinux/unbound.te
@@ -0,0 +1,42 @@
+policy_module(unbound, 0.1.0)
+
+type unbound_t;
+type unbound_conf_t;
+type unbound_exec_t;
+type unbound_initrc_exec_t;
+type unbound_var_run_t;
+
+init_daemon_domain(unbound_t, unbound_exec_t)
+init_script_file(unbound_initrc_exec_t)
+
+role system_r types unbound_t;
+
+# XXX
+# unbound-{checkconf,control} are not protected. Do we need protect them?
+
+# Unbound daemon
+
+auth_use_nsswitch(unbound_t)
+dev_read_urand(unbound_t)
+corenet_all_recvfrom_unlabeled(unbound_t)
+corenet_tcp_bind_all_nodes(unbound_t)
+corenet_tcp_bind_dns_port(unbound_t)
+corenet_tcp_bind_rndc_port(unbound_t)
+corenet_udp_bind_all_nodes(unbound_t)
+corenet_udp_bind_all_unreserved_ports(unbound_t)
+corenet_udp_bind_dns_port(unbound_t)
+files_read_etc_files(unbound_t)
+files_pid_file(unbound_var_run_t)
+files_type(unbound_conf_t)
+libs_use_ld_so(unbound_t)
+libs_use_shared_libs(unbound_t)
+logging_send_syslog_msg(unbound_t)
+manage_files_pattern(unbound_t, unbound_var_run_t, unbound_var_run_t)
+miscfiles_read_localization(unbound_t)
+read_files_pattern(unbound_t, unbound_conf_t, unbound_conf_t)
+
+allow unbound_t self:capability { setuid chown net_bind_service setgid dac_override };
+allow unbound_t self:tcp_socket create_stream_socket_perms;
+allow unbound_t self:udp_socket create_socket_perms;
+
+###################################################
diff --git a/contrib/unbound/contrib/unbound-host.nagios.patch b/contrib/unbound/contrib/unbound-host.nagios.patch
new file mode 100644
index 0000000..5b249b6
--- /dev/null
+++ b/contrib/unbound/contrib/unbound-host.nagios.patch
@@ -0,0 +1,134 @@
+Index: smallapp/unbound-host.c
+===================================================================
+--- smallapp/unbound-host.c (revision 2115)
++++ smallapp/unbound-host.c (working copy)
+@@ -62,9 +62,18 @@
+ #include "libunbound/unbound.h"
+ #include <ldns/ldns.h>
+
++/** status variable ala nagios */
++#define FINAL_STATUS_OK 0
++#define FINAL_STATUS_WARNING 1
++#define FINAL_STATUS_CRITICAL 2
++#define FINAL_STATUS_UNKNOWN 3
++
+ /** verbosity for unbound-host app */
+ static int verb = 0;
+
++/** variable to determine final output */
++static int final_status = FINAL_STATUS_UNKNOWN;
++
+ /** Give unbound-host usage, and exit (1). */
+ static void
+ usage()
+@@ -93,7 +102,7 @@
+ printf("Version %s\n", PACKAGE_VERSION);
+ printf("BSD licensed, see LICENSE in source package for details.\n");
+ printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+
+ /** determine if str is ip4 and put into reverse lookup format */
+@@ -138,7 +147,7 @@
+ *res = strdup(buf);
+ if(!*res) {
+ fprintf(stderr, "error: out of memory\n");
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ return 1;
+ }
+@@ -158,7 +167,7 @@
+ }
+ if(!res) {
+ fprintf(stderr, "error: out of memory\n");
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ return res;
+ }
+@@ -172,7 +181,7 @@
+ if(r == 0 && strcasecmp(t, "TYPE0") != 0 &&
+ strcmp(t, "") != 0) {
+ fprintf(stderr, "error unknown type %s\n", t);
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ return r;
+ }
+@@ -191,7 +200,7 @@
+ if(r == 0 && strcasecmp(c, "CLASS0") != 0 &&
+ strcmp(c, "") != 0) {
+ fprintf(stderr, "error unknown class %s\n", c);
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ return r;
+ }
+@@ -207,6 +216,19 @@
+ return "(insecure)";
+ }
+
++/** update the final status for the exit code */
++void
++update_final_status(struct ub_result* result)
++{
++ if (final_status == FINAL_STATUS_UNKNOWN || final_status == FINAL_STATUS_OK) {
++ if (result->secure) final_status = FINAL_STATUS_OK;
++ else if (result->bogus) final_status = FINAL_STATUS_CRITICAL;
++ else final_status = FINAL_STATUS_WARNING;
++ }
++ else if (final_status == FINAL_STATUS_WARNING && result->bogus)
++ final_status = FINAL_STATUS_CRITICAL;
++}
++
+ /** nice string for type */
+ static void
+ pretty_type(char* s, size_t len, int t)
+@@ -353,7 +375,7 @@
+ } else {
+ fprintf(stderr, "could not parse "
+ "reply packet to ANY query\n");
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ ldns_pkt_free(p);
+
+@@ -388,9 +410,10 @@
+ ret = ub_resolve(ctx, q, t, c, &result);
+ if(ret != 0) {
+ fprintf(stderr, "resolve error: %s\n", ub_strerror(ret));
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ pretty_output(q, t, c, result, docname);
++ update_final_status(result);
+ ret = result->nxdomain;
+ ub_resolve_free(result);
+ return ret;
+@@ -427,7 +450,7 @@
+ {
+ if(r != 0) {
+ fprintf(stderr, "error: %s\n", ub_strerror(r));
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ }
+
+@@ -448,7 +471,7 @@
+ ctx = ub_ctx_create();
+ if(!ctx) {
+ fprintf(stderr, "error: out of memory\n");
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+
+ /* parse the options */
+@@ -509,5 +532,5 @@
+ usage();
+
+ lookup(ctx, argv[0], qtype, qclass);
+- return 0;
++ return final_status;
+ }
diff --git a/contrib/unbound/contrib/unbound.init b/contrib/unbound/contrib/unbound.init
new file mode 100644
index 0000000..747f94e
--- /dev/null
+++ b/contrib/unbound/contrib/unbound.init
@@ -0,0 +1,139 @@
+#!/bin/sh
+#
+# unbound This shell script takes care of starting and stopping
+# unbound (DNS server).
+#
+# chkconfig: - 14 86
+# description: unbound is a Domain Name Server (DNS) \
+# that is used to resolve host names to IP addresses.
+
+### BEGIN INIT INFO
+# Provides: $named unbound
+# Required-Start: $network $local_fs
+# Required-Stop: $network $local_fs
+# Should-Start: $syslog
+# Should-Stop: $syslog
+# Short-Description: unbound recursive Domain Name Server.
+# Description: unbound is a Domain Name Server (DNS)
+# that is used to resolve host names to IP addresses.
+### END INIT INFO
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+exec="/usr/sbin/unbound"
+prog="unbound"
+config="/var/unbound/unbound.conf"
+pidfile="/var/unbound/unbound.pid"
+rootdir="/var/unbound"
+
+[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
+
+lockfile=/var/lock/subsys/$prog
+
+start() {
+ [ -x $exec ] || exit 5
+ [ -f $config ] || exit 6
+ echo -n $"Starting $prog: "
+
+ # setup root jail
+ if [ -s /etc/localtime ]; then
+ [ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
+ if [ ! -e ${rootdir}/etc/localtime ] || /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
+ cp -fp /etc/localtime ${rootdir}/etc/localtime
+ fi;
+ fi;
+ if [ -s /etc/resolv.conf ]; then
+ [ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
+ if [ ! -e ${rootdir}/etc/resolv.conf ] || /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
+ cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
+ fi;
+ fi;
+ if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
+ [ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
+ [ -e ${rootdir}/dev/log ] || touch ${rootdir}/dev/log
+ mount --bind -n /dev/log ${rootdir}/dev/log >/dev/null 2>&1;
+ fi;
+ if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
+ [ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
+ [ -e ${rootdir}/dev/random ] || touch ${rootdir}/dev/random
+ mount --bind -n /dev/random ${rootdir}/dev/random >/dev/null 2>&1;
+ fi;
+
+ # if not running, start it up here
+ daemon $exec
+ retval=$?
+ echo
+ [ $retval -eq 0 ] && touch $lockfile
+ return $retval
+}
+
+stop() {
+ echo -n $"Stopping $prog: "
+ # stop it here, often "killproc $prog"
+ killproc -p $pidfile $prog
+ retval=$?
+ echo
+ [ $retval -eq 0 ] && rm -f $lockfile
+ if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
+ umount ${rootdir}/dev/log >/dev/null 2>&1
+ fi;
+ if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
+ umount ${rootdir}/dev/random >/dev/null 2>&1
+ fi;
+ return $retval
+}
+
+restart() {
+ stop
+ start
+}
+
+reload() {
+ kill -HUP `cat $pidfile`
+}
+
+force_reload() {
+ restart
+}
+
+rh_status() {
+ # run checks to determine if the service is running or use generic status
+ status -p $pidfile $prog
+}
+
+rh_status_q() {
+ rh_status -p $pidfile >/dev/null 2>&1
+}
+
+case "$1" in
+ start)
+ rh_status_q && exit 0
+ $1
+ ;;
+ stop)
+ rh_status_q || exit 0
+ $1
+ ;;
+ restart)
+ $1
+ ;;
+ reload)
+ rh_status_q || exit 7
+ $1
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ status)
+ rh_status
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+ exit 2
+esac
+exit $?
diff --git a/contrib/unbound/contrib/unbound.init_fedora b/contrib/unbound/contrib/unbound.init_fedora
new file mode 100644
index 0000000..9f7e442
--- /dev/null
+++ b/contrib/unbound/contrib/unbound.init_fedora
@@ -0,0 +1,119 @@
+#!/bin/sh
+#
+# unbound This shell script takes care of starting and stopping
+# unbound (DNS server).
+#
+# chkconfig: - 14 86
+# description: unbound is a Domain Name Server (DNS) \
+# that is used to resolve host names to IP addresses.
+
+### BEGIN INIT INFO
+# Provides: unbound
+# Required-Start: $network $local_fs
+# Required-Stop: $network $local_fs
+# Should-Start: $syslog
+# Should-Stop: $syslog
+# Short-Description: unbound recursive Domain Name Server.
+# Description: unbound is a Domain Name Server (DNS)
+# that is used to resolve host names to IP addresses.
+### END INIT INFO
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+exec="/usr/sbin/unbound"
+config="/var/lib/unbound/unbound.conf"
+rootdir="/var/lib/unbound"
+pidfile="/var/run/unbound/unbound.pid"
+
+[ -e /etc/sysconfig/unbound ] && . /etc/sysconfig/unbound
+
+lockfile=/var/lock/subsys/unbound
+
+start() {
+ [ -x $exec ] || exit 5
+ [ -f $config ] || exit 6
+ echo -n $"Starting unbound: "
+
+ if [ ! -e ${rootdir}/etc/resolv.conf ] || /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
+ cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
+ fi;
+ if [ ! -e ${rootdir}/etc/localtime ] || /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
+ cp -fp /etc/localtime ${rootdir}/etc/localtime
+ fi;
+ mount --bind -n /dev/log ${rootdir}/dev/log >/dev/null 2>&1;
+ mount --bind -n /dev/random ${rootdir}/dev/random >/dev/null 2>&1;
+ mount --bind -n /var/run/unbound ${rootdir}/var/run/unbound >/dev/null 2>&1;
+
+ # if not running, start it up here
+ daemon $exec
+ retval=$?
+ [ $retval -eq 0 ] && touch $lockfile
+ echo
+}
+
+stop() {
+ echo -n $"Stopping unbound: "
+ # stop it here, often "killproc unbound"
+ killproc -p $pidfile unbound
+ retval=$?
+ [ $retval -eq 0 ] && rm -f $lockfile
+ for mountfile in /dev/log /dev/random /etc/localtime /etc/resolv.conf /var/run/unbound
+ do
+ if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}''${mountfile}'' /proc/mounts; then
+ umount ${rootdir}$mountfile >/dev/null 2>&1
+ fi;
+ done
+ echo
+}
+
+restart() {
+ stop
+ start
+}
+
+reload() {
+ kill -HUP `cat $pidfile`
+}
+
+force_reload() {
+ restart
+}
+
+rh_status() {
+ # run checks to determine if the service is running or use generic status
+ status -p $pidfile unbound
+}
+
+rh_status_q() {
+ rh_status -p $pidfile >/dev/null 2>&1
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ restart
+ ;;
+ reload)
+ reload
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ status)
+ rh_status
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+ exit 2
+esac
+exit $?
diff --git a/contrib/unbound/contrib/unbound.plist b/contrib/unbound/contrib/unbound.plist
new file mode 100644
index 0000000..15e1162
--- /dev/null
+++ b/contrib/unbound/contrib/unbound.plist
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >
+<plist version="1.0">
+<!--
+Unbound plist file for use by MacOSX launchd(8) using launchctl(1).
+Copy this file to /Library/LaunchDaemons. Launchd keeps unbound running.
+
+Setup your unbound.conf with the following additional settings.
+server:
+ do-daemonize: no
+ username: ""
+ chroot: ""
+ directory: ""
+These actions are performed by launchd (for the option values, see below).
+
+-->
+<dict>
+ <key>Label</key>
+ <string>unbound</string>
+
+ <key>ProgramArguments</key>
+ <array>
+ <string>unbound</string>
+ </array>
+
+ <key>UserName</key>
+ <string>unbound</string>
+
+ <key>RootDirectory</key>
+ <string>/usr/local/etc/unbound</string>
+
+ <key>WorkingDirectory</key>
+ <string>/usr/local/etc/unbound</string>
+
+ <key>KeepAlive</key>
+ <true/>
+
+ <key>RunAtLoad</key>
+ <true/>
+
+</dict>
+</plist>
diff --git a/contrib/unbound/contrib/unbound.spec b/contrib/unbound/contrib/unbound.spec
new file mode 100644
index 0000000..6ddc5f1
--- /dev/null
+++ b/contrib/unbound/contrib/unbound.spec
@@ -0,0 +1,112 @@
+Summary: Validating, recursive, and caching DNS resolver
+Name: unbound
+Version: 1.4.18
+Release: 1%{?dist}
+License: BSD
+Url: http://www.nlnetlabs.nl/unbound/
+Source: http://www.unbound.net/downloads/%{name}-%{version}.tar.gz
+#Source1: unbound.init
+Group: System Environment/Daemons
+Requires: ldns
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildRequires: flex, openssl-devel, expat-devel, ldns-devel
+
+%description
+Unbound is a validating, recursive, and caching DNS resolver.
+
+The C implementation of Unbound is developed and maintained by NLnet
+Labs. It is based on ideas and algorithms taken from a java prototype
+developed by Verisign labs, Nominet, Kirei and ep.net.
+
+Unbound is designed as a set of modular components, so that also
+DNSSEC (secure DNS) validation and stub-resolvers (that do not run
+as a server, but are linked into an application) are easily possible.
+
+The source code is under a BSD License.
+
+%prep
+%setup -q
+
+# configure with /var/unbound/unbound.conf so that all default chroot,
+# pidfile and config file are in /var/unbound, ready for chroot jail set up.
+%configure --with-conf-file=%{_localstatedir}/%{name}/unbound.conf --disable-rpath
+
+%build
+#%{__make} %{?_smp_mflags}
+make
+
+%install
+rm -rf %{buildroot}
+%{__make} DESTDIR=%{buildroot} install
+install -d 0700 %{buildroot}%{_localstatedir}/%{name}
+install -d 0755 %{buildroot}%{_initrddir}
+install -m 0755 contrib/unbound.init %{buildroot}%{_initrddir}/unbound
+# add symbolic link from /etc/unbound.conf -> /var/unbound/unbound.conf
+ln -s %{_localstatedir}/unbound/unbound.conf %{buildroot}%{_sysconfdir}/unbound.conf
+# remove static library from install (fedora packaging guidelines)
+rm -f %{buildroot}%{_libdir}/libunbound.a %{buildroot}%{_libdir}/libunbound.la
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root,-)
+%doc doc/README doc/CREDITS doc/LICENSE doc/FEATURES
+%attr(0755,root,root) %{_initrddir}/%{name}
+%attr(0700,%{name},%{name}) %dir %{_localstatedir}/%{name}
+%attr(0644,%{name},%{name}) %config(noreplace) %{_localstatedir}/%{name}/unbound.conf
+%attr(0644,%{name},%{name}) %config(noreplace) %{_sysconfdir}/unbound.conf
+%{_sbindir}/*
+%{_mandir}/*/*
+%{_includedir}/*
+%{_libdir}/libunbound*
+
+%pre
+getent group unbound >/dev/null || groupadd -r unbound
+getent passwd unbound >/dev/null || \
+useradd -r -g unbound -d /var/unbound -s /sbin/nologin \
+ -c "unbound name daemon" unbound
+exit 0
+
+%post
+# This adds the proper /etc/rc*.d links for the script
+/sbin/chkconfig --add %{name}
+
+%preun
+if [ $1 -eq 0 ]; then
+ /sbin/service %{name} stop >/dev/null 2>&1
+ /sbin/chkconfig --del %{name}
+ # remove root jail
+ rm -f /var/unbound/dev/log /var/unbound/dev/random /var/unbound/etc/localtime /var/unbound/etc/resolv.conf >/dev/null 2>&1
+ rmdir /var/unbound/dev >/dev/null 2>&1 || :
+ rmdir /var/unbound/etc >/dev/null 2>&1 || :
+ rmdir /var/unbound >/dev/null 2>&1 || :
+fi
+
+%postun
+if [ "$1" -ge "1" ]; then
+ /sbin/service %{name} condrestart >/dev/null 2>&1 || :
+fi
+
+%changelog
+* Thu Jul 13 2011 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.4.8
+- ldns required and ldns-devel required for build, no more ldns-builtin.
+
+* Thu Mar 17 2011 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.4.8
+- removed --disable-gost, assume recent openssl on the destination platform.
+
+* Wed Mar 16 2011 Harold Jones <hajones@verisign.com> - 1.4.8
+- Bump version number to latest
+- Add expat-devel to BuildRequires
+- Added --disable-gost for building on CentOS 5.x
+- Added --with-ldns-builtin for CentOS 5.x
+
+* Thu May 22 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.0.0
+- contrib changes from Patrick Vande Walle.
+
+* Thu Apr 25 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.12
+- Using parts from ports collection entry by Jaap Akkerhuis.
+- Using Fedoraproject wiki guidelines.
+
+* Wed Apr 23 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.11
+- Initial version.
diff --git a/contrib/unbound/contrib/unbound.spec_fedora b/contrib/unbound/contrib/unbound.spec_fedora
new file mode 100644
index 0000000..e7e9ac0
--- /dev/null
+++ b/contrib/unbound/contrib/unbound.spec_fedora
@@ -0,0 +1,433 @@
+# not ready yet
+%{?!with_python: %global with_python 1}
+
+%if %{with_python}
+%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
+%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
+%endif
+
+Summary: Validating, recursive, and caching DNS(SEC) resolver
+Name: unbound
+Version: 1.4.13
+Release: 1%{?dist}
+License: BSD
+Url: http://www.nlnetlabs.nl/unbound/
+Source: http://www.unbound.net/downloads/%{name}-%{version}.tar.gz
+Source1: unbound.init
+Source2: unbound.conf
+Source3: unbound.munin
+Source4: unbound_munin_
+Source5: root.key
+Patch1: unbound-1.2-glob.patch
+
+Group: System Environment/Daemons
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildRequires: flex, openssl-devel , ldns-devel >= 1.5.0,
+BuildRequires: libevent-devel expat-devel
+%if %{with_python}
+BuildRequires: python-devel swig
+%endif
+# Required for SVN versions
+# BuildRequires: bison
+
+Requires(post): chkconfig
+Requires(preun): chkconfig
+Requires(preun): initscripts
+Requires(postun): initscripts
+Requires: ldns >= 1.5.0
+Requires(pre): shadow-utils
+
+Obsoletes: dnssec-conf < 1.27-2
+Provides: dnssec-conf = 1.27-1
+
+%description
+Unbound is a validating, recursive, and caching DNS(SEC) resolver.
+
+The C implementation of Unbound is developed and maintained by NLnet
+Labs. It is based on ideas and algorithms taken from a java prototype
+developed by Verisign labs, Nominet, Kirei and ep.net.
+
+Unbound is designed as a set of modular components, so that also
+DNSSEC (secure DNS) validation and stub-resolvers (that do not run
+as a server, but are linked into an application) are easily possible.
+
+%package munin
+Summary: Plugin for the munin / munin-node monitoring package
+Group: System Environment/Daemons
+Requires: munin-node
+Requires: %{name} = %{version}-%{release}, bc
+
+%description munin
+Plugin for the munin / munin-node monitoring package
+
+%package devel
+Summary: Development package that includes the unbound header files
+Group: Development/Libraries
+Requires: %{name}-libs = %{version}-%{release}, openssl-devel, ldns-devel
+
+%description devel
+The devel package contains the unbound library and the include files
+
+%package libs
+Summary: Libraries used by the unbound server and client applications
+Group: Applications/System
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+Requires: openssl
+
+%description libs
+Contains libraries used by the unbound server and client applications
+
+%if %{with_python}
+%package python
+Summary: Python modules and extensions for unbound
+Group: Applications/System
+Requires: %{name}-libs = %{version}-%{release}
+
+%description python
+Python modules and extensions for unbound
+%endif
+
+%prep
+%setup -q
+%patch1 -p1
+
+%build
+%configure --with-ldns= --with-libevent --with-pthreads --with-ssl \
+ --disable-rpath --disable-static \
+ --with-conf-file=%{_sysconfdir}/%{name}/unbound.conf \
+ --with-pidfile=%{_localstatedir}/run/%{name}/%{name}.pid \
+%if %{with_python}
+ --with-pythonmodule --with-pyunbound \
+%endif
+ --enable-sha2 --disable-gost
+%{__make} %{?_smp_mflags}
+
+%install
+rm -rf %{buildroot}
+%{__make} DESTDIR=%{buildroot} install
+install -d 0755 %{buildroot}%{_initrddir}
+install -m 0755 %{SOURCE1} %{buildroot}%{_initrddir}/unbound
+install -m 0755 %{SOURCE2} %{buildroot}%{_sysconfdir}/unbound
+# Install munin plugin and its softlinks
+install -d 0755 %{buildroot}%{_sysconfdir}/munin/plugin-conf.d
+install -m 0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/munin/plugin-conf.d/unbound
+install -d 0755 %{buildroot}%{_datadir}/munin/plugins/
+install -m 0755 %{SOURCE4} %{buildroot}%{_datadir}/munin/plugins/unbound
+for plugin in unbound_munin_hits unbound_munin_queue unbound_munin_memory unbound_munin_by_type unbound_munin_by_class unbound_munin_by_opcode unbound_munin_by_rcode unbound_munin_by_flags unbound_munin_histogram; do
+ ln -s unbound %{buildroot}%{_datadir}/munin/plugins/$plugin
+done
+
+# install root and DLV key
+install -m 0644 %{SOURCE5} %{SOURCE6} %{buildroot}%{_sysconfdir}/unbound/
+
+# remove static library from install (fedora packaging guidelines)
+rm %{buildroot}%{_libdir}/*.la
+%if %{with_python}
+rm %{buildroot}%{python_sitearch}/*.la
+%endif
+
+mkdir -p %{buildroot}%{_localstatedir}/run/unbound
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root,-)
+%doc doc/README doc/CREDITS doc/LICENSE doc/FEATURES
+%attr(0755,root,root) %{_initrddir}/%{name}
+%attr(0755,root,root) %dir %{_sysconfdir}/%{name}
+%ghost %attr(0755,unbound,unbound) %dir %{_localstatedir}/run/%{name}
+%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/unbound.conf
+%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/root.key
+%{_sbindir}/*
+%{_mandir}/*/*
+
+%if %{with_python}
+%files python
+%defattr(-,root,root,-)
+%{python_sitearch}/*
+%doc libunbound/python/examples/*
+%doc pythonmod/examples/*
+%endif
+
+%files munin
+%defattr(-,root,root,-)
+%config(noreplace) %{_sysconfdir}/munin/plugin-conf.d/unbound
+%{_datadir}/munin/plugins/unbound*
+
+%files devel
+%defattr(-,root,root,-)
+%{_libdir}/libunbound.so
+%{_includedir}/unbound.h
+%doc README
+
+%files libs
+%defattr(-,root,root,-)
+%{_libdir}/libunbound.so.*
+%doc doc/README doc/LICENSE
+
+%pre
+getent group unbound >/dev/null || groupadd -r unbound
+getent passwd unbound >/dev/null || \
+useradd -r -g unbound -d %{_sysconfdir}/unbound -s /sbin/nologin \
+-c "Unbound DNS resolver" unbound
+exit 0
+
+%post
+/sbin/chkconfig --add %{name}
+
+%post libs -p /sbin/ldconfig
+
+%preun
+if [ "$1" -eq 0 ]; then
+ /sbin/service %{name} stop >/dev/null 2>&1
+ /sbin/chkconfig --del %{name}
+fi
+
+%postun
+if [ "$1" -ge "1" ]; then
+ /sbin/service %{name} condrestart >/dev/null 2>&1 || :
+fi
+
+%postun libs -p /sbin/ldconfig
+
+%changelog
+* Tue Sep 06 2011 Paul Wouters <paul@xelerance.com> - 1.4.13-1
+- Updated to 1.4.13
+- Fix install location of pythonmod from sitelib to sitearch
+- Removed patches merged in by upstream
+- Removed versioned openssl dep, it differs per branch
+
+* Mon Aug 08 2011 Paul Wouters <paul@xelerance.com> - 1.4.12-3
+- Added pythonmod docs and examples
+- Fix for python module load in the server (Tom Hendrikx)
+- No longer enable --enable-debug as it causes degraded performance
+ under load.
+
+* Mon Jul 18 2011 Paul Wouters <paul@xelerance.com> - 1.4.12-1
+- Updated to 1.4.12
+
+* Sun Jul 03 2011 Paul Wouters <paul@xelerance.com> - 1.4.11-1
+- Updated to 1.4.11
+- removed integrated CVE patch
+- updated stock unbound.conf for new options introduced
+
+* Mon Jun 06 2011 Paul Wouters <paul@xelerance.com> - 1.4.10-1
+- Added ghost for /var/run/unbound (bz#656710)
+
+* Mon Jun 06 2011 Paul Wouters <paul@xelerance.com> - 1.4.9-3
+- rebuilt
+
+* Wed May 25 2011 Paul Wouters <paul@xelerance.com> - 1.4.9-2
+- Applied patch for CVE-2011-1922 DoS vulnerability
+
+* Sun Mar 27 2011 Paul Wouters <paul@xelerance.com> - 1.4.9-1
+- Updated to 1.4.9
+
+* Sat Feb 12 2011 Paul Wouters <paul@xelerance.com> - 1.4.8-2
+- rebuilt
+
+* Tue Jan 25 2011 Paul Wouters <paul@xelerance.com> - 1.4.8-1
+- Updated to 1.4.8
+- Enable root key for DNSSEC
+- Fix unbound-munin to use proper file (could cause excessive logging)
+- Build unbound-python per default
+- Disable gost as Fedora/EPEL does not allow ECC and has mangled openssl
+
+* Tue Oct 26 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-4
+- Revert last build - it was on the wrong branch
+
+* Tue Oct 26 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-3
+- Disable do-ipv6 per default - causes severe degradation on non-ipv6 machines
+ (see comments in inbound.conf)
+
+* Tue Jun 15 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-2
+- Bump release - forgot to upload the new tar ball.
+
+* Tue Jun 15 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-1
+- Upgraded to 1.4.5
+
+* Mon May 31 2010 Paul Wouters <paul@xelerance.com> - 1.4.4-2
+- Added accidentally omitted svn patches to cvs
+
+* Mon May 31 2010 Paul Wouters <paul@xelerance.com> - 1.4.4-1
+- Upgraded to 1.4.4 with svn patches
+- Obsolete dnssec-conf to ensure it is de-installed
+
+* Thu Mar 11 2010 Paul Wouters <paul@xelerance.com> - 1.4.3-1
+- Update to 1.4.3 that fixes 64bit crasher
+
+* Tue Mar 09 2010 Paul Wouters <paul@xelerance.com> - 1.4.2-1
+- Updated to 1.4.2
+- Updated unbound.conf with new options
+- Enabled pre-fetching DNSKEY records (DNSSEC speedup)
+- Enabled re-fetching popular records before they expire
+- Enabled logging of DNSSEC validation errors
+
+* Mon Mar 01 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-5
+- Overriding -D_GNU_SOURCE is no longer needed. This fixes DSO issues
+ with pthreads
+
+* Wed Feb 24 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-3
+- Change make/configure lines to attempt to fix -lphtread linking issue
+
+* Thu Feb 18 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-2
+- Removed dependency for dnssec-conf
+- Added ISC DLV key (formerly in dnssec-conf)
+- Fixup old DLV locations in unbound.conf file via %%post
+- Fix parent child disagreement handling and no-ipv6 present [svn r1953]
+
+* Tue Jan 05 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-1
+- Updated to 1.4.1
+- Changed %%define to %%global
+
+* Thu Oct 08 2009 Paul Wouters <paul@xelerance.com> - 1.3.4-2
+- Bump version
+
+* Thu Oct 08 2009 Paul Wouters <paul@xelerance.com> - 1.3.4-1
+- Upgraded to 1.3.4. Security fix with validating NSEC3 records
+
+* Fri Aug 21 2009 Tomas Mraz <tmraz@redhat.com> - 1.3.3-2
+- rebuilt with new openssl
+
+* Mon Aug 17 2009 Paul Wouters <paul@xelerance.com> - 1.3.3-1
+- Updated to 1.3.3
+
+* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.0-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Sat Jun 20 2009 Paul Wouters <paul@xelerance.com> - 1.3.0-2
+- Added missing glob patch to cvs
+- Place python macros within the %%with_python check
+
+* Sat Jun 20 2009 Paul Wouters <paul@xelerance.com> - 1.3.0-1
+- Updated to 1.3.0
+- Added unbound-python sub package. disabled for now
+- Patch from svn to fix DLV lookups
+- Patches from svn to detect wrong truncated response from BIND 9.6.1 with
+ minimal-responses)
+- Added Default-Start and Default-Stop to unbound.init
+- Re-enabled --enable-sha2
+- Re-enabled glob.patch
+
+* Wed May 20 2009 Paul Wouters <paul@xelerance.com> - 1.2.1-7
+- unbound-iterator.patch was not committed
+
+* Wed May 20 2009 Paul Wouters <paul@xelerance.com> - 1.2.1-6
+- Fix for https://bugzilla.redhat.com/show_bug.cgi?id=499793
+
+* Tue Mar 17 2009 Paul Wouters <paul@xelerance.com> - 1.2.1-5
+- Use --nocheck to avoid giving an error on missing unbound-remote certs/keys
+
+* Tue Mar 10 2009 Adam Tkac <atkac redhat com> - 1.2.1-4
+- enable DNSSEC only if it is enabled in sysconfig/dnssec
+
+* Mon Mar 09 2009 Adam Tkac <atkac redhat com> - 1.2.1-3
+- add DNSSEC support to initscript and enabled it per default
+- add requires dnssec-conf
+
+* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.1-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Tue Feb 10 2009 Paul Wouters <paul@xelerance.com - 1.2.1-1
+- updated to 1.2.1
+
+* Sun Jan 18 2009 Tomas Mraz <tmraz@redhat.com> - 1.2.0-2
+- rebuild with new openssl
+
+* Wed Jan 14 2009 Paul Wouters <paul@xelerance.com - 1.2.0-1
+- Updated to 1.2.0
+- Added dependency on minimum SSL for CVE-2008-5077
+- Added dependency on bc for unbound-munin
+- Added minimum requirement of libevent 1.4.5. Crashes with older versions
+ (note: libevent is stale in EL-4 and not in EL-5, needs fixing there)
+- Removed dependency on selinux-policy (will get used when available)
+- Enable options as per draft-wijngaards-dnsext-resolver-side-mitigation-00.txt
+- Enable unwanted-reply-threshold to mitigate against a Kaminsky attack
+- Enable val-clean-additional to drop addition unsigned data from signed
+ response.
+- Removed patches (got merged into upstream)
+
+* Mon Jan 5 2009 Paul Wouters <paul@xelerance.com> - 1.1.1-7
+- Modified scandir patch to silently fail when wildcard matches nothing
+- Patch to allow unbound-checkconf to find empty wildcard matches
+
+* Mon Jan 5 2009 Paul Wouters <paul@xelerance.com> - 1.1.1-6
+- Added scandir patch for trusted-keys-file: option, which
+ is used to load multiple dnssec keys in bind file format
+
+* Mon Dec 8 2008 Paul Wouters <paul@xelerance.com> - 1.1.1-4
+- Added Requires: for selinux-policy >= 3.5.13-33 for proper SElinux rules.
+
+* Mon Dec 1 2008 Paul Wouters <paul@xelerance.com> - 1.1.1-3
+- We did not own the /etc/unbound directory (#474020)
+- Fixed cvs anomalies
+
+* Fri Nov 28 2008 Adam Tkac <atkac redhat com> - 1.1.1-2
+- removed all obsolete chroot related stuff
+- label control certs after generation correctly
+
+* Thu Nov 20 2008 Paul Wouters <paul@xelerance.com> - 1.1.1-1
+- Updated to unbound 1.1.1 which fixes a crasher and
+ addresses nlnetlabs bug #219
+
+* Wed Nov 19 2008 Paul Wouters <paul@xelerance.com> - 1.1.0-3
+- Remove the chroot, obsoleted by SElinux
+- Add additional munin plugin links supported by unbound plugin
+- Move configuration directory from /var/lib/unbound to /etc/unbound
+- Modified unbound.init and unbound.conf to account for chroot changes
+- Updated unbound.conf with new available options
+- Enabled dns-0x20 protection per default
+
+* Wed Nov 19 2008 Adam Tkac <atkac redhat com> - 1.1.0-2
+- unbound-1.1.0-log_open.patch
+ - make sure log is opened before chroot call
+ - tracked as http://www.nlnetlabs.nl/bugs/show_bug.cgi?id=219
+- removed /dev/log and /var/run/unbound and /etc/resolv.conf from
+ chroot, not needed
+- don't mount files in chroot, it causes problems during updates
+- fixed typo in default config file
+
+* Fri Nov 14 2008 Paul Wouters <paul@xelerance.com> - 1.1.0-1
+- Updated to version 1.1.0
+- Updated unbound.conf's statistics options and remote-control
+ to work properly for munin
+- Added unbound-munin package
+- Generate unbound remote-control key/certs on first startup
+- Required ldns is now 1.4.0
+
+* Wed Oct 22 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-5
+- Only call ldconfig in -libs package
+- Move configure into build section
+- devel subpackage should only depend on libs subpackage
+
+* Tue Oct 21 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-4
+- Fix CFLAGS getting lost in build
+- Don't enable interface-automatic:yes because that
+ causes unbound to listen on 0.0.0.0 instead of 127.0.0.1
+
+* Sun Oct 19 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-3
+- Split off unbound-libs, make build verbose
+
+* Thu Oct 9 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-2
+- FSB compliance, chroot fixes, initscript fixes
+
+* Thu Sep 11 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-1
+- Upgraded to 1.0.2
+
+* Wed Jul 16 2008 Paul Wouters <paul@xelerance.com> - 1.0.1-1
+- upgraded to new release
+
+* Wed May 21 2008 Paul Wouters <paul@xelerance.com> - 1.0.0-2
+- Build against ldns-1.3.0
+
+* Wed May 21 2008 Paul Wouters <paul@xelerance.com> - 1.0.0-1
+- Split of -devel package, fixed dependencies, make rpmlint happy
+
+* Thu Apr 25 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.12
+- Using parts from ports collection entry by Jaap Akkerhuis.
+- Using Fedoraproject wiki guidelines.
+
+* Wed Apr 23 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.11
+- Initial version.
diff --git a/contrib/unbound/contrib/unbound_cache.cmd b/contrib/unbound/contrib/unbound_cache.cmd
new file mode 100644
index 0000000..532162b
--- /dev/null
+++ b/contrib/unbound/contrib/unbound_cache.cmd
@@ -0,0 +1,105 @@
+@echo off
+rem --------------------------------------------------------------
+rem -- DNS cache save/load script
+rem --
+rem -- Version 1.2
+rem -- By Yuri Voinov (c) 2014
+rem --------------------------------------------------------------
+
+rem Variables
+set prefix="C:\Program Files (x86)"
+set program_path=%prefix%\Unbound
+set uc=%program_path%\unbound-control.exe
+set fname="unbound_cache.dmp"
+
+rem Check Unbound installed
+if exist %uc% goto start
+echo Unbound control not found. Exiting...
+exit 1
+
+:start
+
+rem arg1 - command (optional)
+rem arg2 - file name (optional)
+set arg1=%1
+set arg2=%2
+
+if /I "%arg1%" == "-h" goto help
+
+if "%arg1%" == "" (
+echo Loading cache from %program_path%\%fname%
+dir /a %program_path%\%fname%
+type %program_path%\%fname%|%uc% load_cache
+goto end
+)
+
+if defined %arg2% (goto Not_Defined) else (goto Defined)
+
+rem If file not specified; use default dump file
+:Not_defined
+if /I "%arg1%" == "-s" (
+echo Saving cache to %program_path%\%fname%
+%uc% dump_cache>%program_path%\%fname%
+dir /a %program_path%\%fname%
+echo ok
+goto end
+)
+
+if /I "%arg1%" == "-l" (
+echo Loading cache from %program_path%\%fname%
+dir /a %program_path%\%fname%
+type %program_path%\%fname%|%uc% load_cache
+goto end
+)
+
+if /I "%arg1%" == "-r" (
+echo Saving cache to %program_path%\%fname%
+dir /a %program_path%\%fname%
+%uc% dump_cache>%program_path%\%fname%
+echo ok
+echo Loading cache from %program_path%\%fname%
+type %program_path%\%fname%|%uc% load_cache
+goto end
+)
+
+rem If file name specified; use this filename
+:Defined
+if /I "%arg1%" == "-s" (
+echo Saving cache to %arg2%
+%uc% dump_cache>%arg2%
+dir /a %arg2%
+echo ok
+goto end
+)
+
+if /I "%arg1%" == "-l" (
+echo Loading cache from %arg2%
+dir /a %arg2%
+type %arg2%|%uc% load_cache
+goto end
+)
+
+if /I "%arg1%" == "-r" (
+echo Saving cache to %arg2%
+dir /a %arg2%
+%uc% dump_cache>%arg2%
+echo ok
+echo Loading cache from %arg2%
+type %arg2%|%uc% load_cache
+goto end
+)
+
+:help
+echo Usage: unbound_cache.cmd [-s] or [-l] or [-r] or [-h] [filename]
+echo.
+echo l - Load - default mode. Warming up Unbound DNS cache from saved file. cache-ttl must be high value.
+echo s - Save - save Unbound DNS cache contents to plain file with domain names.
+echo r - Reload - reloadind new cache entries and refresh existing cache
+echo h - this screen.
+echo filename - file to save/load dumped cache. If not specified, %program_path%\%fname% will be used instead.
+echo Note: Run without any arguments will be in default mode.
+echo Also, unbound-control must be configured.
+exit 1
+
+:end
+exit 0
diff --git a/contrib/unbound/contrib/unbound_cache.sh b/contrib/unbound/contrib/unbound_cache.sh
new file mode 100755
index 0000000..b3e876b
--- /dev/null
+++ b/contrib/unbound/contrib/unbound_cache.sh
@@ -0,0 +1,174 @@
+#!/sbin/sh
+
+# --------------------------------------------------------------
+# -- DNS cache save/load script
+# --
+# -- Version 1.2
+# -- By Yuri Voinov (c) 2006, 2014
+# --------------------------------------------------------------
+#
+# ident "@(#)unbound_cache.sh 1.2 14/10/30 YV"
+#
+
+#############
+# Variables #
+#############
+
+# Installation base dir
+CONF="/etc/opt/csw/unbound"
+BASE="/opt/csw"
+
+# Unbound binaries
+UC="$BASE/sbin/unbound-control"
+FNAME="unbound_cache.dmp"
+
+# OS utilities
+BASENAME=`which basename`
+CAT=`which cat`
+CUT=`which cut`
+ECHO=`which echo`
+EXPR=`which expr`
+GETOPT=`which getopt`
+ID=`which id`
+LS=`which ls`
+
+###############
+# Subroutines #
+###############
+
+usage_note ()
+{
+# Script usage note
+ $ECHO "Usage: `$BASENAME $0` [-s] or [-l] or [-r] or [-h] [filename]"
+ $ECHO .
+ $ECHO "l - Load - default mode. Warming up Unbound DNS cache from saved file. cache-ttl must be high value."
+ $ECHO "s - Save - save Unbound DNS cache contents to plain file with domain names."
+ $ECHO "r - Reload - reloadind new cache entries and refresh existing cache"
+ $ECHO "h - this screen."
+ $ECHO "filename - file to save/load dumped cache. If not specified, $CONF/$FNAME will be used instead."
+ $ECHO "Note: Run without any arguments will be in default mode."
+ $ECHO " Also, unbound-control must be configured."
+ exit 0
+}
+
+root_check ()
+{
+ if [ ! `$ID | $CUT -f1 -d" "` = "uid=0(root)" ]; then
+ $ECHO "ERROR: You must be super-user to run this script."
+ exit 1
+ fi
+}
+
+check_uc ()
+{
+ if [ ! -f "$UC" ]; then
+ $ECHO .
+ $ECHO "ERROR: $UC not found. Exiting..."
+ exit 1
+ fi
+}
+
+check_saved_file ()
+{
+ filename=$1
+ if [ ! -z "$filename" -a ! -f "$filename" ]; then
+ $ECHO .
+ $ECHO "ERROR: File $filename does not exists. Save it first."
+ exit 1
+ elif [ ! -f "$CONF/$FNAME" ]; then
+ $ECHO .
+ $ECHO "ERROR: File $CONF/$FNAME does not exists. Save it first."
+ exit 1
+ fi
+}
+
+save_cache ()
+{
+ # Save unbound cache
+ filename=$1
+ if [ -z "$filename" ]; then
+ $ECHO "Saving cache in $CONF/$FNAME..."
+ $UC dump_cache>$CONF/$FNAME
+ $LS -lh $CONF/$FNAME
+ else
+ $ECHO "Saving cache in $filename..."
+ $UC dump_cache>$filename
+ $LS -lh $filename
+ fi
+ $ECHO "ok"
+}
+
+load_cache ()
+{
+ # Load saved cache contents and warmup cache
+ filename=$1
+ if [ -z "$filename" ]; then
+ $ECHO "Loading cache from saved $CONF/$FNAME..."
+ $LS -lh $CONF/$FNAME
+ check_saved_file $filename
+ $CAT $CONF/$FNAME|$UC load_cache
+ else
+ $ECHO "Loading cache from saved $filename..."
+ $LS -lh $filename
+ check_saved_file $filename
+ $CAT $filename|$UC load_cache
+ fi
+}
+
+reload_cache ()
+{
+ # Reloading and refresh existing cache and saved dump
+ filename=$1
+ save_cache $filename
+ load_cache $filename
+}
+
+##############
+# Main block #
+##############
+
+# Root check
+root_check
+
+# Check unbound-control
+check_uc
+
+# Check command-line arguments
+if [ "x$*" = "x" ]; then
+ # If arguments list empty,load cache by default
+ load_cache
+else
+ arg_list=$*
+ # Parse command line
+ set -- `$GETOPT sSlLrRhH: $arg_list` || {
+ usage_note 1>&2
+ }
+
+ # Read arguments
+ for i in $arg_list
+ do
+ case $i in
+ -s | -S) save="1";;
+ -l | -L) save="0";;
+ -r | -R) save="2";;
+ -h | -H | \?) usage_note;;
+ *) shift
+ file=$1
+ break;;
+ esac
+ shift
+ done
+
+ # Remove trailing --
+ shift `$EXPR $OPTIND - 1`
+fi
+
+if [ "$save" = "1" ]; then
+ save_cache $file
+elif [ "$save" = "0" ]; then
+ load_cache $file
+elif [ "$save" = "2" ]; then
+ reload_cache $file
+fi
+
+exit 0 \ No newline at end of file
diff --git a/contrib/unbound/contrib/unbound_cacti.tar.gz b/contrib/unbound/contrib/unbound_cacti.tar.gz
new file mode 100644
index 0000000..36bbdec
--- /dev/null
+++ b/contrib/unbound/contrib/unbound_cacti.tar.gz
Binary files differ
diff --git a/contrib/unbound/contrib/unbound_munin_ b/contrib/unbound/contrib/unbound_munin_
new file mode 100755
index 0000000..69e9f31
--- /dev/null
+++ b/contrib/unbound/contrib/unbound_munin_
@@ -0,0 +1,574 @@
+#!/bin/sh
+#
+# plugin for munin to monitor usage of unbound servers.
+# To install copy this to /usr/local/share/munin/plugins/unbound_munin_
+# and use munin-node-configure (--suggest, --shell).
+#
+# (C) 2008 W.C.A. Wijngaards. BSD Licensed.
+#
+# To install; enable statistics and unbound-control in unbound.conf
+# server: extended-statistics: yes
+# statistics-cumulative: no
+# statistics-interval: 0
+# remote-control: control-enable: yes
+# Run the command unbound-control-setup to generate the key files.
+#
+# Environment variables for this script
+# statefile - where to put temporary statefile.
+# unbound_conf - where the unbound.conf file is located.
+# unbound_control - where to find unbound-control executable.
+# spoof_warn - what level to warn about spoofing
+# spoof_crit - what level to crit about spoofing
+#
+# You can set them in your munin/plugin-conf.d/plugins.conf file
+# with:
+# [unbound*]
+# user root
+# env.statefile /usr/local/var/munin/plugin-state/unbound-state
+# env.unbound_conf /usr/local/etc/unbound/unbound.conf
+# env.unbound_control /usr/local/sbin/unbound-control
+# env.spoof_warn 1000
+# env.spoof_crit 100000
+#
+# This plugin can create different graphs depending on what name
+# you link it as (with ln -s) into the plugins directory
+# You can link it multiple times.
+# If you are only a casual user, the _hits and _by_type are most interesting,
+# possibly followed by _by_rcode.
+#
+# unbound_munin_hits - base volume, cache hits, unwanted traffic
+# unbound_munin_queue - to monitor the internal requestlist
+# unbound_munin_memory - memory usage
+# unbound_munin_by_type - incoming queries by type
+# unbound_munin_by_class - incoming queries by class
+# unbound_munin_by_opcode - incoming queries by opcode
+# unbound_munin_by_rcode - answers by rcode, validation status
+# unbound_munin_by_flags - incoming queries by flags
+# unbound_munin_histogram - histogram of query resolving times
+#
+# Magic markers - optional - used by installation scripts and
+# munin-config: (originally contrib family but munin-node-configure ignores it)
+#
+#%# family=auto
+#%# capabilities=autoconf suggest
+
+# POD documentation
+: <<=cut
+=head1 NAME
+
+unbound_munin_ - Munin plugin to monitor the Unbound DNS resolver.
+
+=head1 APPLICABLE SYSTEMS
+
+System with unbound daemon.
+
+=head1 CONFIGURATION
+
+ [unbound*]
+ user root
+ env.statefile /usr/local/var/munin/plugin-state/unbound-state
+ env.unbound_conf /usr/local/etc/unbound/unbound.conf
+ env.unbound_control /usr/local/sbin/unbound-control
+ env.spoof_warn 1000
+ env.spoof_crit 100000
+
+Use the .env settings to override the defaults.
+
+=head1 USAGE
+
+Can be used to present different graphs. Use ln -s for that name in
+the plugins directory to enable the graph.
+unbound_munin_hits - base volume, cache hits, unwanted traffic
+unbound_munin_queue - to monitor the internal requestlist
+unbound_munin_memory - memory usage
+unbound_munin_by_type - incoming queries by type
+unbound_munin_by_class - incoming queries by class
+unbound_munin_by_opcode - incoming queries by opcode
+unbound_munin_by_rcode - answers by rcode, validation status
+unbound_munin_by_flags - incoming queries by flags
+unbound_munin_histogram - histogram of query resolving times
+
+=head1 AUTHOR
+
+Copyright 2008 W.C.A. Wijngaards
+
+=head1 LICENSE
+
+BSD
+
+=cut
+
+state=${statefile:-/usr/local/var/munin/plugin-state/unbound-state}
+conf=${unbound_conf:-/usr/local/etc/unbound/unbound.conf}
+ctrl=${unbound_control:-/usr/local/sbin/unbound-control}
+warn=${spoof_warn:-1000}
+crit=${spoof_crit:-100000}
+lock=$state.lock
+
+# number of seconds between polling attempts.
+# makes the statefile hang around for at least this many seconds,
+# so that multiple links of this script can share the results.
+lee=55
+
+# to keep things within 19 characters
+ABBREV="-e s/total/t/ -e s/thread/t/ -e s/num/n/ -e s/query/q/ -e s/answer/a/ -e s/unwanted/u/ -e s/requestlist/ql/ -e s/type/t/ -e s/class/c/ -e s/opcode/o/ -e s/rcode/r/ -e s/edns/e/ -e s/mem/m/ -e s/cache/c/ -e s/mod/m/"
+
+# get value from $1 into return variable $value
+get_value ( ) {
+ value="`grep '^'$1'=' $state | sed -e 's/^.*=//'`"
+ if test "$value"x = ""x; then
+ value="0"
+ fi
+}
+
+# download the state from the unbound server.
+get_state ( ) {
+ # obtain lock for fetching the state
+ # because there is a race condition in fetching and writing to file
+
+ # see if the lock is stale, if so, take it
+ if test -f $lock ; then
+ pid="`cat $lock 2>&1`"
+ kill -0 "$pid" >/dev/null 2>&1
+ if test $? -ne 0 -a "$pid" != $$ ; then
+ echo $$ >$lock
+ fi
+ fi
+
+ i=0
+ while test ! -f $lock || test "`cat $lock 2>&1`" != $$; do
+ while test -f $lock; do
+ # wait
+ i=`expr $i + 1`
+ if test $i -gt 1000; then
+ sleep 1;
+ fi
+ if test $i -gt 1500; then
+ echo "error locking $lock" "=" `cat $lock`
+ rm -f $lock
+ exit 1
+ fi
+ done
+ # try to get it
+ echo $$ >$lock
+ done
+ # do not refetch if the file exists and only LEE seconds old
+ if test -f $state; then
+ now=`date +%s`
+ get_value "time.now"
+ value="`echo $value | sed -e 's/\..*$//'`"
+ if test $now -lt `expr $value + $lee`; then
+ rm -f $lock
+ return
+ fi
+ fi
+ $ctrl -c $conf stats > $state
+ if test $? -ne 0; then
+ echo "error retrieving data from unbound server"
+ rm -f $lock
+ exit 1
+ fi
+ rm -f $lock
+}
+
+if test "$1" = "autoconf" ; then
+ if test ! -f $conf; then
+ echo no "($conf does not exist)"
+ exit 1
+ fi
+ if test ! -d `dirname $state`; then
+ echo no "(`dirname $state` directory does not exist)"
+ exit 1
+ fi
+ echo yes
+ exit 0
+fi
+
+if test "$1" = "suggest" ; then
+ echo "hits"
+ echo "queue"
+ echo "memory"
+ echo "by_type"
+ echo "by_class"
+ echo "by_opcode"
+ echo "by_rcode"
+ echo "by_flags"
+ echo "histogram"
+ exit 0
+fi
+
+# determine my type, by name
+id=`echo $0 | sed -e 's/^.*unbound_munin_//'`
+if test "$id"x = ""x; then
+ # some default to keep people sane.
+ id="hits"
+fi
+
+# if $1 exists in statefile, config is echoed with label $2
+exist_config ( ) {
+ mn=`echo $1 | sed $ABBREV | tr . _`
+ if grep '^'$1'=' $state >/dev/null 2>&1; then
+ echo "$mn.label $2"
+ echo "$mn.min 0"
+ echo "$mn.type ABSOLUTE"
+ fi
+}
+
+# print label and min 0 for a name $1 in unbound format
+p_config ( ) {
+ mn=`echo $1 | sed $ABBREV | tr . _`
+ echo $mn.label "$2"
+ echo $mn.min 0
+ echo $mn.type $3
+}
+
+if test "$1" = "config" ; then
+ if test ! -f $state; then
+ get_state
+ fi
+ case $id in
+ hits)
+ echo "graph_title Unbound DNS traffic and cache hits"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
+ sed -e 's/=.*//'`; do
+ exist_config $x "queries handled by `basename $x .num.queries`"
+ done
+ p_config "total.num.queries" "total queries from clients" "ABSOLUTE"
+ p_config "total.num.cachehits" "cache hits" "ABSOLUTE"
+ p_config "total.num.prefetch" "cache prefetch" "ABSOLUTE"
+ p_config "num.query.tcp" "TCP queries" "ABSOLUTE"
+ p_config "num.query.tcpout" "TCP out queries" "ABSOLUTE"
+ p_config "num.query.ipv6" "IPv6 queries" "ABSOLUTE"
+ p_config "unwanted.queries" "queries that failed acl" "ABSOLUTE"
+ p_config "unwanted.replies" "unwanted or unsolicited replies" "ABSOLUTE"
+ echo "u_replies.warning $warn"
+ echo "u_replies.critical $crit"
+ echo "graph_info DNS queries to the recursive resolver. The unwanted replies could be innocent duplicate packets, late replies, or spoof threats."
+ ;;
+ queue)
+ echo "graph_title Unbound requestlist size"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel number of queries"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ p_config "total.requestlist.avg" "Average size of queue on insert" "GAUGE"
+ p_config "total.requestlist.max" "Max size of queue (in 5 min)" "GAUGE"
+ p_config "total.requestlist.overwritten" "Number of queries replaced by new ones" "GAUGE"
+ p_config "total.requestlist.exceeded" "Number of queries dropped due to lack of space" "GAUGE"
+ echo "graph_info The queries that did not hit the cache and need recursion service take up space in the requestlist. If there are too many queries, first queries get overwritten, and at last resort dropped."
+ ;;
+ memory)
+ echo "graph_title Unbound memory usage"
+ echo "graph_args --base 1024 -l 0"
+ echo "graph_vlabel memory used in bytes"
+ echo "graph_category DNS"
+ p_config "mem.total.sbrk" "Total memory" "GAUGE"
+ p_config "mem.cache.rrset" "RRset cache memory" "GAUGE"
+ p_config "mem.cache.message" "Message cache memory" "GAUGE"
+ p_config "mem.mod.iterator" "Iterator module memory" "GAUGE"
+ p_config "mem.mod.validator" "Validator module and key cache memory" "GAUGE"
+ p_config "msg.cache.count" "msg cache count" "GAUGE"
+ p_config "rrset.cache.count" "rrset cache count" "GAUGE"
+ p_config "infra.cache.count" "infra cache count" "GAUGE"
+ p_config "key.cache.count" "key cache count" "GAUGE"
+ echo "graph_info The memory used by unbound."
+ ;;
+ by_type)
+ echo "graph_title Unbound DNS queries by type"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ for x in `grep "^num.query.type" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ tp=`echo $nm | sed -e s/num.query.type.//`
+ p_config "$nm" "$tp" "ABSOLUTE"
+ done
+ echo "graph_info queries by DNS RR type queried for"
+ ;;
+ by_class)
+ echo "graph_title Unbound DNS queries by class"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ for x in `grep "^num.query.class" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ tp=`echo $nm | sed -e s/num.query.class.//`
+ p_config "$nm" "$tp" "ABSOLUTE"
+ done
+ echo "graph_info queries by DNS RR class queried for."
+ ;;
+ by_opcode)
+ echo "graph_title Unbound DNS queries by opcode"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ for x in `grep "^num.query.opcode" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ tp=`echo $nm | sed -e s/num.query.opcode.//`
+ p_config "$nm" "$tp" "ABSOLUTE"
+ done
+ echo "graph_info queries by opcode in the query packet."
+ ;;
+ by_rcode)
+ echo "graph_title Unbound DNS answers by return code"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel answer packets / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ for x in `grep "^num.answer.rcode" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ tp=`echo $nm | sed -e s/num.answer.rcode.//`
+ p_config "$nm" "$tp" "ABSOLUTE"
+ done
+ p_config "num.answer.secure" "answer secure" "ABSOLUTE"
+ p_config "num.answer.bogus" "answer bogus" "ABSOLUTE"
+ p_config "num.rrset.bogus" "num rrsets marked bogus" "ABSOLUTE"
+ echo "graph_info answers sorted by return value. rrsets bogus is the number of rrsets marked bogus per \${graph_period} by the validator"
+ ;;
+ by_flags)
+ echo "graph_title Unbound DNS incoming queries by flags"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ p_config "num.query.flags.QR" "QR (query reply) flag" "ABSOLUTE"
+ p_config "num.query.flags.AA" "AA (auth answer) flag" "ABSOLUTE"
+ p_config "num.query.flags.TC" "TC (truncated) flag" "ABSOLUTE"
+ p_config "num.query.flags.RD" "RD (recursion desired) flag" "ABSOLUTE"
+ p_config "num.query.flags.RA" "RA (rec avail) flag" "ABSOLUTE"
+ p_config "num.query.flags.Z" "Z (zero) flag" "ABSOLUTE"
+ p_config "num.query.flags.AD" "AD (auth data) flag" "ABSOLUTE"
+ p_config "num.query.flags.CD" "CD (check disabled) flag" "ABSOLUTE"
+ p_config "num.query.edns.present" "EDNS OPT present" "ABSOLUTE"
+ p_config "num.query.edns.DO" "DO (DNSSEC OK) flag" "ABSOLUTE"
+ echo "graph_info This graphs plots the flags inside incoming queries. For example, if QR, AA, TC, RA, Z flags are set, the query can be rejected. RD, AD, CD and DO are legitimately set by some software."
+ ;;
+ histogram)
+ echo "graph_title Unbound DNS histogram of reply time"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ echo hcache.label "cache hits"
+ echo hcache.min 0
+ echo hcache.type ABSOLUTE
+ echo hcache.draw AREA
+ echo hcache.colour 999999
+ echo h64ms.label "0 msec - 66 msec"
+ echo h64ms.min 0
+ echo h64ms.type ABSOLUTE
+ echo h64ms.draw STACK
+ echo h64ms.colour 0000FF
+ echo h128ms.label "66 msec - 131 msec"
+ echo h128ms.min 0
+ echo h128ms.type ABSOLUTE
+ echo h128ms.colour 1F00DF
+ echo h128ms.draw STACK
+ echo h256ms.label "131 msec - 262 msec"
+ echo h256ms.min 0
+ echo h256ms.type ABSOLUTE
+ echo h256ms.draw STACK
+ echo h256ms.colour 3F00BF
+ echo h512ms.label "262 msec - 524 msec"
+ echo h512ms.min 0
+ echo h512ms.type ABSOLUTE
+ echo h512ms.draw STACK
+ echo h512ms.colour 5F009F
+ echo h1s.label "524 msec - 1 sec"
+ echo h1s.min 0
+ echo h1s.type ABSOLUTE
+ echo h1s.draw STACK
+ echo h1s.colour 7F007F
+ echo h2s.label "1 sec - 2 sec"
+ echo h2s.min 0
+ echo h2s.type ABSOLUTE
+ echo h2s.draw STACK
+ echo h2s.colour 9F005F
+ echo h4s.label "2 sec - 4 sec"
+ echo h4s.min 0
+ echo h4s.type ABSOLUTE
+ echo h4s.draw STACK
+ echo h4s.colour BF003F
+ echo h8s.label "4 sec - 8 sec"
+ echo h8s.min 0
+ echo h8s.type ABSOLUTE
+ echo h8s.draw STACK
+ echo h8s.colour DF001F
+ echo h16s.label "8 sec - ..."
+ echo h16s.min 0
+ echo h16s.type ABSOLUTE
+ echo h16s.draw STACK
+ echo h16s.colour FF0000
+ echo "graph_info Histogram of the reply times for queries."
+ ;;
+ esac
+
+ exit 0
+fi
+
+# do the stats itself
+get_state
+
+# get the time elapsed
+get_value "time.elapsed"
+if test $value = 0 || test $value = "0.000000"; then
+ echo "error: time elapsed 0 or could not retrieve data"
+ exit 1
+fi
+elapsed="$value"
+
+# print value for $1
+print_value ( ) {
+ mn=`echo $1 | sed $ABBREV | tr . _`
+ get_value $1
+ echo "$mn.value" $value
+}
+
+# print value if line already found in $2
+print_value_line ( ) {
+ mn=`echo $1 | sed $ABBREV | tr . _`
+ value="`echo $2 | sed -e 's/^.*=//'`"
+ echo "$mn.value" $value
+}
+
+
+case $id in
+hits)
+ for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
+ sed -e 's/=.*//'` total.num.queries \
+ total.num.cachehits total.num.prefetch num.query.tcp \
+ num.query.tcpout num.query.ipv6 unwanted.queries \
+ unwanted.replies; do
+ if grep "^"$x"=" $state >/dev/null 2>&1; then
+ print_value $x
+ fi
+ done
+ ;;
+queue)
+ for x in total.requestlist.avg total.requestlist.max \
+ total.requestlist.overwritten total.requestlist.exceeded; do
+ print_value $x
+ done
+ ;;
+memory)
+ mn=`echo mem.total.sbrk | sed $ABBREV | tr . _`
+ get_value 'mem.total.sbrk'
+ if test $value -eq 0; then
+ chk=`echo $ctrl | sed -e 's/-control$/-checkconf/'`
+ pidf=`$chk -o pidfile $conf 2>&1`
+ pid=`cat $pidf 2>&1`
+ value=`ps -p "$pid" -o rss= 2>&1`
+ if test "`expr $value + 1 - 1 2>&1`" -eq "$value" 2>&1; then
+ value=`expr $value \* 1024`
+ else
+ value=0
+ fi
+ fi
+ echo "$mn.value" $value
+ for x in mem.cache.rrset mem.cache.message mem.mod.iterator \
+ mem.mod.validator msg.cache.count rrset.cache.count \
+ infra.cache.count key.cache.count; do
+ print_value $x
+ done
+ ;;
+by_type)
+ for x in `grep "^num.query.type" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ print_value_line $nm $x
+ done
+ ;;
+by_class)
+ for x in `grep "^num.query.class" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ print_value_line $nm $x
+ done
+ ;;
+by_opcode)
+ for x in `grep "^num.query.opcode" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ print_value_line $nm $x
+ done
+ ;;
+by_rcode)
+ for x in `grep "^num.answer.rcode" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ print_value_line $nm $x
+ done
+ print_value "num.answer.secure"
+ print_value "num.answer.bogus"
+ print_value "num.rrset.bogus"
+ ;;
+by_flags)
+ for x in num.query.flags.QR num.query.flags.AA num.query.flags.TC num.query.flags.RD num.query.flags.RA num.query.flags.Z num.query.flags.AD num.query.flags.CD num.query.edns.present num.query.edns.DO; do
+ print_value $x
+ done
+ ;;
+histogram)
+ get_value total.num.cachehits
+ echo hcache.value $value
+ r=0
+ for x in histogram.000000.000000.to.000000.000001 \
+ histogram.000000.000001.to.000000.000002 \
+ histogram.000000.000002.to.000000.000004 \
+ histogram.000000.000004.to.000000.000008 \
+ histogram.000000.000008.to.000000.000016 \
+ histogram.000000.000016.to.000000.000032 \
+ histogram.000000.000032.to.000000.000064 \
+ histogram.000000.000064.to.000000.000128 \
+ histogram.000000.000128.to.000000.000256 \
+ histogram.000000.000256.to.000000.000512 \
+ histogram.000000.000512.to.000000.001024 \
+ histogram.000000.001024.to.000000.002048 \
+ histogram.000000.002048.to.000000.004096 \
+ histogram.000000.004096.to.000000.008192 \
+ histogram.000000.008192.to.000000.016384 \
+ histogram.000000.016384.to.000000.032768 \
+ histogram.000000.032768.to.000000.065536; do
+ get_value $x
+ r=`expr $r + $value`
+ done
+ echo h64ms.value $r
+ get_value histogram.000000.065536.to.000000.131072
+ echo h128ms.value $value
+ get_value histogram.000000.131072.to.000000.262144
+ echo h256ms.value $value
+ get_value histogram.000000.262144.to.000000.524288
+ echo h512ms.value $value
+ get_value histogram.000000.524288.to.000001.000000
+ echo h1s.value $value
+ get_value histogram.000001.000000.to.000002.000000
+ echo h2s.value $value
+ get_value histogram.000002.000000.to.000004.000000
+ echo h4s.value $value
+ get_value histogram.000004.000000.to.000008.000000
+ echo h8s.value $value
+ r=0
+ for x in histogram.000008.000000.to.000016.000000 \
+ histogram.000016.000000.to.000032.000000 \
+ histogram.000032.000000.to.000064.000000 \
+ histogram.000064.000000.to.000128.000000 \
+ histogram.000128.000000.to.000256.000000 \
+ histogram.000256.000000.to.000512.000000 \
+ histogram.000512.000000.to.001024.000000 \
+ histogram.001024.000000.to.002048.000000 \
+ histogram.002048.000000.to.004096.000000 \
+ histogram.004096.000000.to.008192.000000 \
+ histogram.008192.000000.to.016384.000000 \
+ histogram.016384.000000.to.032768.000000 \
+ histogram.032768.000000.to.065536.000000 \
+ histogram.065536.000000.to.131072.000000 \
+ histogram.131072.000000.to.262144.000000 \
+ histogram.262144.000000.to.524288.000000; do
+ get_value $x
+ r=`expr $r + $value`
+ done
+ echo h16s.value $r
+ ;;
+esac
diff --git a/contrib/unbound/contrib/unbound_smf22.tar.gz b/contrib/unbound/contrib/unbound_smf22.tar.gz
new file mode 100644
index 0000000..e4c51c3
--- /dev/null
+++ b/contrib/unbound/contrib/unbound_smf22.tar.gz
Binary files differ
diff --git a/contrib/unbound/contrib/update-anchor.sh b/contrib/unbound/contrib/update-anchor.sh
new file mode 100755
index 0000000..95032a0
--- /dev/null
+++ b/contrib/unbound/contrib/update-anchor.sh
@@ -0,0 +1,158 @@
+#!/bin/sh
+# update-anchor.sh, update a trust anchor.
+# Copyright 2008, W.C.A. Wijngaards
+# This file is BSD licensed, see doc/LICENSE.
+
+# which validating lookup to use.
+ubhost=unbound-host
+
+usage ( )
+{
+ echo "usage: update-anchor [-r hs] [-b] <zone name> <trust anchor file>"
+ echo " performs an update of trust anchor file"
+ echo " the trust anchor file is overwritten with the latest keys"
+ echo " the trust anchor file should contain only keys for one zone"
+ echo " -b causes keyfile to be made in bind format."
+ echo " without -b the file is made in unbound format."
+ echo " "
+ echo "alternate:"
+ echo " update-anchor [-r hints] [-b] -d directory"
+ echo " update all <zone>.anchor files in the directory."
+ echo " "
+ echo " name the files br.anchor se.anchor ..., and include them in"
+ echo " the validating resolver config file."
+ echo " put keys for the root in a file with the name root.anchor."
+ echo ""
+ echo "-r root.hints use different root hints. Strict option order."
+ echo ""
+ echo "Exit code 0 means anchors updated, 1 no changes, others are errors."
+ exit 2
+}
+
+if test $# -eq 0; then
+ usage
+fi
+bindformat="no"
+filearg='-f'
+roothints=""
+if test X"$1" = "X-r"; then
+ shift
+ roothints="$1"
+ shift
+fi
+if test X"$1" = "X-b"; then
+ shift
+ bindformat="yes"
+ filearg='-F'
+fi
+if test $# -ne 2; then
+ echo "arguments wrong."
+ usage
+fi
+
+do_update ( ) {
+ # arguments: <zonename> <keyfile>
+ zonename="$1"
+ keyfile="$2"
+ tmpfile="/tmp/update-anchor.$$"
+ tmp2=$tmpfile.2
+ tmp3=$tmpfile.3
+ rh=""
+ if test -n "$roothints"; then
+ echo "server: root-hints: '$roothints'" > $tmp3
+ rh="-C $tmp3"
+ fi
+ $ubhost -v $rh $filearg "$keyfile" -t DNSKEY "$zonename" >$tmpfile
+ if test $? -ne 0; then
+ rm -f $tmpfile
+ echo "Error: Could not update zone $zonename anchor file $keyfile"
+ echo "Cause: $ubhost lookup failed"
+ echo " (Is the domain decommissioned? Is connectivity lost?)"
+ return 2
+ fi
+
+ # has the lookup been DNSSEC validated?
+ if grep '(secure)$' $tmpfile >/dev/null 2>&1; then
+ :
+ else
+ rm -f $tmpfile
+ echo "Error: Could not update zone $zonename anchor file $keyfile"
+ echo "Cause: result of lookup was not secure"
+ echo " (keys too far out of date? domain changed ownership? need root hints?)"
+ return 3
+ fi
+
+ if test $bindformat = "yes"; then
+ # are there any KSK keys on board?
+ echo 'trusted-keys {' > "$tmp2"
+ if grep ' has DNSKEY record 257' $tmpfile >/dev/null 2>&1; then
+ # store KSK keys in anchor file
+ grep '(secure)$' $tmpfile | \
+ grep ' has DNSKEY record 257' | \
+ sed -e 's/ (secure)$/";/' | \
+ sed -e 's/ has DNSKEY record \([0-9]*\) \([0-9]*\) \([0-9]*\) /. \1 \2 \3 "/' | \
+ sed -e 's/^\.\././' | sort >> "$tmp2"
+ else
+ # store all keys in the anchor file
+ grep '(secure)$' $tmpfile | \
+ sed -e 's/ (secure)$/";/' | \
+ sed -e 's/ has DNSKEY record \([0-9]*\) \([0-9]*\) \([0-9]*\) /. \1 \2 \3 "/' | \
+ sed -e 's/^\.\././' | sort >> "$tmp2"
+ fi
+ echo '};' >> "$tmp2"
+ else #not bindformat
+ # are there any KSK keys on board?
+ if grep ' has DNSKEY record 257' $tmpfile >/dev/null 2>&1; then
+ # store KSK keys in anchor file
+ grep '(secure)$' $tmpfile | \
+ grep ' has DNSKEY record 257' | \
+ sed -e 's/ (secure)$//' | \
+ sed -e 's/ has DNSKEY record /. IN DNSKEY /' | \
+ sed -e 's/^\.\././' | sort > "$tmp2"
+ else
+ # store all keys in the anchor file
+ grep '(secure)$' $tmpfile | \
+ sed -e 's/ (secure)$//' | \
+ sed -e 's/ has DNSKEY record /. IN DNSKEY /' | \
+ sed -e 's/^\.\././' | sort > "$tmp2"
+ fi
+ fi # endif-bindformat
+
+ # copy over if changed
+ diff $tmp2 $keyfile >/dev/null 2>&1
+ if test $? -eq 1; then # 0 means no change, 2 means trouble.
+ cat $tmp2 > $keyfile
+ no_updated=0
+ echo "$zonename key file $keyfile updated."
+ else
+ echo "$zonename key file $keyfile unchanged."
+ fi
+
+ rm -f $tmpfile $tmp2 $tmp3
+}
+
+no_updated=1
+if test X"$1" = "X-d"; then
+ tdir="$2"
+ echo "start updating in $2"
+ for x in $tdir/*.anchor; do
+ if test `basename "$x"` = "root.anchor"; then
+ zname="."
+ else
+ zname=`basename "$x" .anchor`
+ fi
+ do_update "$zname" "$x"
+ done
+ echo "done updating in $2"
+else
+ # regular invocation
+ if test X"$1" = "X."; then
+ zname="$1"
+ else
+ # strip trailing dot from zone name
+ zname="`echo $1 | sed -e 's/\.$//'`"
+ fi
+ kfile="$2"
+ do_update $zname $kfile
+fi
+exit $no_updated
diff --git a/contrib/unbound/contrib/validation-reporter.sh b/contrib/unbound/contrib/validation-reporter.sh
new file mode 100755
index 0000000..7c1a421
--- /dev/null
+++ b/contrib/unbound/contrib/validation-reporter.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+# validation reporter - reports validation failures to a collection server.
+# Copyright NLnet Labs, 2010
+# BSD license.
+
+
+###
+# Here is the configuration for the validation reporter
+# it greps the failure lines out of the log and sends them to a server.
+
+# The pidfile for the reporter daemon.
+pidfile="/var/run/validation-reporter.pid"
+
+# The logfile to watch for logged validation failures.
+logfile="/var/log/unbound.log"
+
+# how to notify the upstream
+# nc is netcat, it sends tcp to given host port. It makes a tcp connection
+# and writes one log-line to it (grepped from the logfile).
+# the notify command can be: "nc the.server.name.org 1234"
+# the listening daemon could be: nc -lk 127.0.0.1 1234 >> outputfile &
+notify_cmd="nc localhost 1234"
+
+
+###
+# Below this line is the code for the validation reporter,
+# first the daemon itself, then the controller for the daemon.
+reporter_daemon() {
+ trap "rm -f \"$pidfile\"" EXIT
+ tail -F $logfile | grep --line-buffered "unbound.*info: validation failure" | \
+ while read x; do
+ echo "$x" | $notify_cmd
+ done
+}
+
+
+###
+# controller for daemon.
+start_daemon() {
+ echo "starting reporter"
+ nohup $0 rundaemon </dev/null >/dev/null 2>&1 &
+ echo $! > "$pidfile"
+}
+
+kill_daemon() {
+ echo "stopping reporter"
+ if test -s "$pidfile"; then
+ kill `cat "$pidfile"`
+ # check it is really dead
+ if kill -0 `cat "$pidfile"` >/dev/null 2>&1; then
+ sleep 1
+ while kill -0 `cat "$pidfile"` >/dev/null 2>&1; do
+ kill `cat "$pidfile"` >/dev/null 2>&1
+ echo "waiting for reporter to stop"
+ sleep 1
+ done
+ fi
+ fi
+}
+
+get_status_daemon() {
+ if test -s "$pidfile"; then
+ if kill -0 `cat "$pidfile"`; then
+ return 0;
+ fi
+ fi
+ return 1;
+}
+
+restart_daemon() {
+ kill_daemon
+ start_daemon
+}
+
+condrestart_daemon() {
+ if get_status_daemon; then
+ echo "reporter ("`cat "$pidfile"`") is running"
+ exit 0
+ fi
+ start_daemon
+ exit 0
+}
+
+status_daemon() {
+ if get_status_daemon; then
+ echo "reporter ("`cat "$pidfile"`") is running"
+ exit 0
+ fi
+ echo "reporter is not running"
+ exit 1
+}
+
+case "$1" in
+ rundaemon)
+ reporter_daemon
+ ;;
+ start)
+ start_daemon
+ ;;
+ stop)
+ kill_daemon
+ ;;
+ restart)
+ restart_daemon
+ ;;
+ condrestart)
+ condrestart_daemon
+ ;;
+ status)
+ status_daemon
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|condrestart|status}"
+ exit 2
+ ;;
+esac
+exit $?
diff --git a/contrib/unbound/contrib/warmup.cmd b/contrib/unbound/contrib/warmup.cmd
new file mode 100644
index 0000000..b3895a8
--- /dev/null
+++ b/contrib/unbound/contrib/warmup.cmd
@@ -0,0 +1,153 @@
+@echo off
+
+rem --------------------------------------------------------------
+rem -- Warm up DNS cache script by your own MRU domains or from
+rem -- file when it specified as script argument.
+rem --
+rem -- Version 1.1
+rem -- By Yuri Voinov (c) 2014
+rem --------------------------------------------------------------
+
+rem DNS host address
+set address="127.0.0.1"
+
+rem Check dig installed
+for /f "delims=" %%a in ('where dig') do @set dig=%%a
+if /I "%dig%"=="" echo Dig not found. If installed, add path to PATH environment variable. & exit 1
+echo Dig found: %dig%
+
+set arg=%1%
+
+if defined %arg% (goto builtin) else (goto from_file)
+
+:builtin
+echo Warming up cache by MRU domains...
+for %%a in (
+2gis.ru
+admir.kz
+adobe.com
+agent.mail.ru
+aimp.ru
+akamai.com
+akamai.net
+almaty.tele2.kz
+aol.com
+apple.com
+arin.com
+artlebedev.ru
+auto.mail.ru
+beeline.kz
+bing.com
+blogspot.com
+comodo.com
+dnscrypt.org
+drive.google.com
+drive.mail.ru
+facebook.com
+farmanager.com
+fb.com
+firefox.com
+forum.farmanager.com
+gazeta.ru
+getsharex.com
+gismeteo.ru
+google.com
+google.kz
+google.ru
+googlevideo.com
+goto.kz
+iana.org
+icq.com
+imap.mail.ru
+instagram.com
+intel.com
+irr.kz
+java.com
+kaspersky.com
+kaspersky.ru
+kcell.kz
+krisha.kz
+lady.mail.ru
+lenta.ru
+libreoffice.org
+linkedin.com
+livejournal.com
+mail.google.com
+mail.ru
+microsoft.com
+mozilla.org
+mra.mail.ru
+munin-monitoring.org
+my.mail.ru
+news.bbcimg.co.uk
+news.mail.ru
+newsimg.bbc.net.uk
+nvidia.com
+odnoklassniki.ru
+ok.ru
+opencsw.org
+opendns.com
+opendns.org
+opennet.ru
+opera.com
+oracle.com
+peerbet.ru
+piriform.com
+plugring.farmanager.com
+privoxy.org
+qip.ru
+raidcall.com
+rambler.ru
+reddit.com
+ru.wikipedia.org
+shallalist.de
+skype.com
+snob.ru
+squid-cache.org
+squidclamav.darold.net
+squidguard.org
+ssl.comodo.com
+ssl.verisign.com
+symantec.com
+symantecliveupdate.com
+tele2.kz
+tengrinews.kz
+thunderbird.com
+torproject.org
+torstatus.blutmagie.de
+translate.google.com
+unbound.net
+verisign.com
+vk.com
+vk.me
+vk.ru
+vkontakte.com
+vkontakte.ru
+vlc.org
+watsapp.net
+weather.mail.ru
+windowsupdate.com
+www.baidu.com
+www.bbc.co.uk
+www.internic.net
+www.opennet.ru
+www.topgear.com
+ya.ru
+yahoo.com
+yandex.com
+yandex.ru
+youtube.com
+ytimg.com
+) do "%dig%" %%a @%address% 1>nul 2>nul
+goto end
+
+:from_file
+echo Warming up cache from %1% file...
+%dig% -f %arg% @%address% 1>nul 2>nul
+
+:end
+echo Saving cache...
+if exist unbound_cache.cmd unbound_cache.cmd -s
+echo Done.
+
+exit 0 \ No newline at end of file
diff --git a/contrib/unbound/contrib/warmup.sh b/contrib/unbound/contrib/warmup.sh
new file mode 100755
index 0000000..b4d9135
--- /dev/null
+++ b/contrib/unbound/contrib/warmup.sh
@@ -0,0 +1,150 @@
+#!/bin/sh
+
+# --------------------------------------------------------------
+# -- Warm up DNS cache script by your own MRU domains or from
+# -- file when it specified as script argument.
+# --
+# -- Version 1.1
+# -- By Yuri Voinov (c) 2014
+# --------------------------------------------------------------
+
+# Default DNS host address
+address="127.0.0.1"
+
+cat=`which cat`
+dig=`which dig`
+
+if [ -z "$1" ]; then
+echo "Warming up cache by MRU domains..."
+$dig -f - @$address >/dev/null 2>&1 <<EOT
+2gis.ru
+admir.kz
+adobe.com
+agent.mail.ru
+aimp.ru
+akamai.com
+akamai.net
+almaty.tele2.kz
+aol.com
+apple.com
+arin.com
+artlebedev.ru
+auto.mail.ru
+beeline.kz
+bing.com
+blogspot.com
+clamav.net
+comodo.com
+dnscrypt.org
+drive.google.com
+drive.mail.ru
+facebook.com
+farmanager.com
+fb.com
+firefox.com
+forum.farmanager.com
+gazeta.ru
+getsharex.com
+gismeteo.ru
+google.com
+google.kz
+google.ru
+googlevideo.com
+goto.kz
+iana.org
+icq.com
+imap.mail.ru
+instagram.com
+instagram.com
+intel.com
+irr.kz
+java.com
+kaspersky.com
+kaspersky.ru
+kcell.kz
+krisha.kz
+lady.mail.ru
+lenta.ru
+libreoffice.org
+linkedin.com
+livejournal.com
+mail.google.com
+mail.ru
+microsoft.com
+mozilla.org
+mra.mail.ru
+munin-monitoring.org
+my.mail.ru
+news.bbcimg.co.uk
+news.mail.ru
+newsimg.bbc.net.uk
+nvidia.com
+odnoklassniki.ru
+ok.ru
+opencsw.org
+opendns.com
+opendns.org
+opennet.ru
+opera.com
+oracle.com
+peerbet.ru
+piriform.com
+plugring.farmanager.com
+privoxy.org
+qip.ru
+raidcall.com
+rambler.ru
+reddit.com
+ru.wikipedia.org
+shallalist.de
+skype.com
+snob.ru
+squid-cache.org
+squidclamav.darold.net
+squidguard.org
+ssl.comodo.com
+ssl.verisign.com
+symantec.com
+symantecliveupdate.com
+tele2.kz
+tengrinews.kz
+thunderbird.com
+torproject.org
+torstatus.blutmagie.de
+translate.google.com
+unbound.net
+verisign.com
+vk.com
+vk.me
+vk.ru
+vkontakte.com
+vkontakte.ru
+vlc.org
+watsapp.net
+weather.mail.ru
+windowsupdate.com
+www.baidu.com
+www.bbc.co.uk
+www.internic.net
+www.opennet.ru
+www.topgear.com
+ya.ru
+yahoo.com
+yandex.com
+yandex.ru
+youtube.com
+ytimg.com
+EOT
+else
+ echo "Warming up cache from $1 file..."
+ $cat $1 | $dig -f - @$address >/dev/null 2>&1
+fi
+
+echo "Done."
+
+echo "Saving cache..."
+script=`which unbound_cache.sh`
+[ -f "$script" ] && $script -s
+echo "Done."
+
+exit 0
diff --git a/contrib/unbound/daemon/acl_list.c b/contrib/unbound/daemon/acl_list.c
index 84d099c..d09b46e 100644
--- a/contrib/unbound/daemon/acl_list.c
+++ b/contrib/unbound/daemon/acl_list.c
@@ -45,6 +45,8 @@
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
+#include "services/localzone.h"
+#include "sldns/str2wire.h"
struct acl_list*
acl_list_create(void)
@@ -71,21 +73,21 @@ acl_list_delete(struct acl_list* acl)
}
/** insert new address into acl_list structure */
-static int
+static struct acl_addr*
acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
socklen_t addrlen, int net, enum acl_access control,
int complain_duplicates)
{
- struct acl_addr* node = regional_alloc(acl->region,
+ struct acl_addr* node = regional_alloc_zero(acl->region,
sizeof(struct acl_addr));
if(!node)
- return 0;
+ return NULL;
node->control = control;
if(!addr_tree_insert(&acl->tree, &node->node, addr, addrlen, net)) {
if(complain_duplicates)
verbose(VERB_QUERY, "duplicate acl address ignored.");
}
- return 1;
+ return node;
}
/** apply acl_list string */
@@ -125,6 +127,156 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
return 1;
}
+/** find or create node (NULL on parse or error) */
+static struct acl_addr*
+acl_find_or_create(struct acl_list* acl, const char* str)
+{
+ struct acl_addr* node;
+ struct sockaddr_storage addr;
+ int net;
+ socklen_t addrlen;
+ if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
+ log_err("cannot parse netblock: %s", str);
+ return NULL;
+ }
+ /* find or create node */
+ if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr,
+ addrlen, net))) {
+ /* create node, type 'allow' since otherwise tags are
+ * pointless, can override with specific access-control: cfg */
+ if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr,
+ addrlen, net, acl_allow, 1))) {
+ log_err("out of memory");
+ return NULL;
+ }
+ }
+ return node;
+}
+
+/** apply acl_tag string */
+static int
+acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
+ size_t bitmaplen)
+{
+ struct acl_addr* node;
+ if(!(node=acl_find_or_create(acl, str)))
+ return 0;
+ node->taglen = bitmaplen;
+ node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen);
+ if(!node->taglist) {
+ log_err("out of memory");
+ return 0;
+ }
+ return 1;
+}
+
+/** apply acl_tag_action string */
+static int
+acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg,
+ const char* str, const char* tag, const char* action)
+{
+ struct acl_addr* node;
+ int tagid;
+ enum localzone_type t;
+ if(!(node=acl_find_or_create(acl, str)))
+ return 0;
+ /* allocate array if not yet */
+ if(!node->tag_actions) {
+ node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region,
+ sizeof(*node->tag_actions)*cfg->num_tags);
+ if(!node->tag_actions) {
+ log_err("out of memory");
+ return 0;
+ }
+ node->tag_actions_size = (size_t)cfg->num_tags;
+ }
+ /* parse tag */
+ if((tagid=find_tag_id(cfg, tag)) == -1) {
+ log_err("cannot parse tag (define-tag it): %s %s", str, tag);
+ return 0;
+ }
+ if((size_t)tagid >= node->tag_actions_size) {
+ log_err("tagid too large for array %s %s", str, tag);
+ return 0;
+ }
+ if(!local_zone_str2type(action, &t)) {
+ log_err("cannot parse access control action type: %s %s %s",
+ str, tag, action);
+ return 0;
+ }
+ node->tag_actions[tagid] = (uint8_t)t;
+ return 1;
+}
+
+/** check wire data parse */
+static int
+check_data(const char* data)
+{
+ char buf[65536];
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ size_t len = sizeof(rr);
+ int res;
+ snprintf(buf, sizeof(buf), "%s %s", "example.com.", data);
+ res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL, 0,
+ NULL, 0);
+ if(res == 0)
+ return 1;
+ log_err("rr data [char %d] parse error %s",
+ (int)LDNS_WIREPARSE_OFFSET(res)-13,
+ sldns_get_errorstr_parse(res));
+ return 0;
+}
+
+/** apply acl_tag_data string */
+static int
+acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
+ const char* str, const char* tag, const char* data)
+{
+ struct acl_addr* node;
+ int tagid;
+ char* dupdata;
+ if(!(node=acl_find_or_create(acl, str)))
+ return 0;
+ /* allocate array if not yet */
+ if(!node->tag_datas) {
+ node->tag_datas = (struct config_strlist**)regional_alloc_zero(
+ acl->region, sizeof(*node->tag_datas)*cfg->num_tags);
+ if(!node->tag_datas) {
+ log_err("out of memory");
+ return 0;
+ }
+ node->tag_datas_size = (size_t)cfg->num_tags;
+ }
+ /* parse tag */
+ if((tagid=find_tag_id(cfg, tag)) == -1) {
+ log_err("cannot parse tag (define-tag it): %s %s", str, tag);
+ return 0;
+ }
+ if((size_t)tagid >= node->tag_datas_size) {
+ log_err("tagid too large for array %s %s", str, tag);
+ return 0;
+ }
+
+ /* check data? */
+ if(!check_data(data)) {
+ log_err("cannot parse access-control-tag data: %s %s '%s'",
+ str, tag, data);
+ return 0;
+ }
+
+ dupdata = regional_strdup(acl->region, data);
+ if(!dupdata) {
+ log_err("out of memory");
+ return 0;
+ }
+ if(!cfg_region_strlist_insert(acl->region,
+ &(node->tag_datas[tagid]), dupdata)) {
+ log_err("out of memory");
+ return 0;
+ }
+ return 1;
+}
+
/** read acl_list config */
static int
read_acl_list(struct acl_list* acl, struct config_file* cfg)
@@ -138,6 +290,77 @@ read_acl_list(struct acl_list* acl, struct config_file* cfg)
return 1;
}
+/** read acl tags config */
+static int
+read_acl_tags(struct acl_list* acl, struct config_file* cfg)
+{
+ struct config_strbytelist* np, *p = cfg->acl_tags;
+ cfg->acl_tags = NULL;
+ while(p) {
+ log_assert(p->str && p->str2);
+ if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len)) {
+ config_del_strbytelist(p);
+ return 0;
+ }
+ /* free the items as we go to free up memory */
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p);
+ p = np;
+ }
+ return 1;
+}
+
+/** read acl tag actions config */
+static int
+read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg)
+{
+ struct config_str3list* p, *np;
+ p = cfg->acl_tag_actions;
+ cfg->acl_tag_actions = NULL;
+ while(p) {
+ log_assert(p->str && p->str2 && p->str3);
+ if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2,
+ p->str3)) {
+ config_deltrplstrlist(p);
+ return 0;
+ }
+ /* free the items as we go to free up memory */
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p->str3);
+ free(p);
+ p = np;
+ }
+ return 1;
+}
+
+/** read acl tag datas config */
+static int
+read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg)
+{
+ struct config_str3list* p, *np;
+ p = cfg->acl_tag_datas;
+ cfg->acl_tag_datas = NULL;
+ while(p) {
+ log_assert(p->str && p->str2 && p->str3);
+ if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3)) {
+ config_deltrplstrlist(p);
+ return 0;
+ }
+ /* free the items as we go to free up memory */
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p->str3);
+ free(p);
+ p = np;
+ }
+ return 1;
+}
+
int
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
{
@@ -145,6 +368,12 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
addr_tree_init(&acl->tree);
if(!read_acl_list(acl, cfg))
return 0;
+ if(!read_acl_tags(acl, cfg))
+ return 0;
+ if(!read_acl_tag_actions(acl, cfg))
+ return 0;
+ if(!read_acl_tag_datas(acl, cfg))
+ return 0;
/* insert defaults, with '0' to ignore them if they are duplicates */
if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0))
return 0;
@@ -163,13 +392,18 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
}
enum acl_access
-acl_list_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
+acl_get_control(struct acl_addr* acl)
+{
+ if(acl) return acl->control;
+ return acl_deny;
+}
+
+struct acl_addr*
+acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
socklen_t addrlen)
{
- struct acl_addr* r = (struct acl_addr*)addr_tree_lookup(&acl->tree,
+ return (struct acl_addr*)addr_tree_lookup(&acl->tree,
addr, addrlen);
- if(r) return r->control;
- return acl_deny;
}
size_t
diff --git a/contrib/unbound/daemon/acl_list.h b/contrib/unbound/daemon/acl_list.h
index 2323697..fc0e9ca 100644
--- a/contrib/unbound/daemon/acl_list.h
+++ b/contrib/unbound/daemon/acl_list.h
@@ -87,6 +87,19 @@ struct acl_addr {
struct addr_tree_node node;
/** access control on this netblock */
enum acl_access control;
+ /** tag bitlist */
+ uint8_t* taglist;
+ /** length of the taglist (in bytes) */
+ size_t taglen;
+ /** array per tagnumber of localzonetype(in one byte). NULL if none. */
+ uint8_t* tag_actions;
+ /** size of the tag_actions_array */
+ size_t tag_actions_size;
+ /** array per tagnumber, with per tag a list of rdata strings.
+ * NULL if none. strings are like 'A 127.0.0.1' 'AAAA ::1' */
+ struct config_strlist** tag_datas;
+ /** size of the tag_datas array */
+ size_t tag_datas_size;
};
/**
@@ -110,14 +123,22 @@ void acl_list_delete(struct acl_list* acl);
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg);
/**
- * Lookup address to see its access control status.
+ * Lookup access control status for acl structure.
+ * @param acl: structure for acl storage.
+ * @return: what to do with message from this address.
+ */
+enum acl_access acl_get_control(struct acl_addr* acl);
+
+/**
+ * Lookup address to see its acl structure
* @param acl: structure for address storage.
* @param addr: address to check
* @param addrlen: length of addr.
- * @return: what to do with message from this address.
+ * @return: acl structure from this address.
*/
-enum acl_access acl_list_lookup(struct acl_list* acl,
- struct sockaddr_storage* addr, socklen_t addrlen);
+struct acl_addr*
+acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
+ socklen_t addrlen);
/**
* Get memory used by acl structure.
diff --git a/contrib/unbound/daemon/daemon.c b/contrib/unbound/daemon/daemon.c
index e763f72..2ed9af8f 100644
--- a/contrib/unbound/daemon/daemon.c
+++ b/contrib/unbound/daemon/daemon.c
@@ -204,20 +204,29 @@ daemon_init(void)
signal_handling_record();
checklock_start();
#ifdef HAVE_SSL
+# ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
ERR_load_crypto_strings();
- ERR_load_SSL_strings();
-# ifdef HAVE_OPENSSL_CONFIG
- OPENSSL_config("unbound");
# endif
+ ERR_load_SSL_strings();
# ifdef USE_GOST
(void)sldns_key_EVP_load_gost_id();
# endif
+# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
OpenSSL_add_all_algorithms();
+# else
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+# endif
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
/* grab the COMP method ptr because openssl leaks it */
comp_meth = (void*)SSL_COMP_get_compression_methods();
# endif
+# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
+# else
+ (void)OPENSSL_init_ssl(0, NULL);
+# endif
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
if(!ub_openssl_lock_init())
fatal_exit("could not init openssl locks");
@@ -407,6 +416,8 @@ daemon_create_workers(struct daemon* daemon)
}
daemon->workers = (struct worker**)calloc((size_t)daemon->num,
sizeof(struct worker*));
+ if(!daemon->workers)
+ fatal_exit("out of memory during daemon init");
if(daemon->cfg->dnstap) {
#ifdef USE_DNSTAP
daemon->dtenv = dt_create(daemon->cfg->dnstap_socket_path,
@@ -589,13 +600,12 @@ daemon_cleanup(struct daemon* daemon)
log_thread_set(NULL);
/* clean up caches because
* a) RRset IDs will be recycled after a reload, causing collisions
- * b) validation config can change, thus rrset, msg, keycache clear
- * The infra cache is kept, the timing and edns info is still valid */
+ * b) validation config can change, thus rrset, msg, keycache clear */
slabhash_clear(&daemon->env->rrset_cache->table);
slabhash_clear(daemon->env->msg_cache);
local_zones_delete(daemon->local_zones);
daemon->local_zones = NULL;
- /* key cache is cleared by module desetup during next daemon_init() */
+ /* key cache is cleared by module desetup during next daemon_fork() */
daemon_remote_clear(daemon->rc);
for(i=0; i<daemon->num; i++)
worker_delete(daemon->workers[i]);
@@ -647,18 +657,27 @@ daemon_delete(struct daemon* daemon)
# endif
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
# ifndef S_SPLINT_S
+# if OPENSSL_VERSION_NUMBER < 0x10100000
sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free);
+# endif
# endif
# endif
# ifdef HAVE_OPENSSL_CONFIG
EVP_cleanup();
+# if OPENSSL_VERSION_NUMBER < 0x10100000
ENGINE_cleanup();
+# endif
CONF_modules_free();
# endif
+# ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
- ERR_remove_state(0);
+# endif
+# ifdef HAVE_ERR_FREE_STRINGS
ERR_free_strings();
+# endif
+# if OPENSSL_VERSION_NUMBER < 0x10100000
RAND_cleanup();
+# endif
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
ub_openssl_lock_delete();
# endif
diff --git a/contrib/unbound/daemon/daemon.h b/contrib/unbound/daemon/daemon.h
index 86ddab1..48c0b4f 100644
--- a/contrib/unbound/daemon/daemon.h
+++ b/contrib/unbound/daemon/daemon.h
@@ -45,9 +45,6 @@
#include "util/locks.h"
#include "util/alloc.h"
#include "services/modstack.h"
-#ifdef UB_ON_WINDOWS
-# include "util/winsock_event.h"
-#endif
struct config_file;
struct worker;
struct listen_port;
diff --git a/contrib/unbound/daemon/remote.c b/contrib/unbound/daemon/remote.c
index c2112de..3fe6650 100644
--- a/contrib/unbound/daemon/remote.c
+++ b/contrib/unbound/daemon/remote.c
@@ -46,9 +46,12 @@
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
-#ifndef HEADER_DH_H
+#ifdef HAVE_OPENSSL_DH_H
#include <openssl/dh.h>
#endif
+#ifdef HAVE_OPENSSL_BN_H
+#include <openssl/bn.h>
+#endif
#include <ctype.h>
#include "daemon/remote.h"
@@ -140,47 +143,64 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
/*
* The following function was generated using the openssl utility, using
- * the command : "openssl dhparam -dsaparam -C 1024"
+ * the command : "openssl dhparam -C 2048"
* (some openssl versions reject DH that is 'too small', eg. 512).
*/
#ifndef S_SPLINT_S
-DH *get_dh1024()
-{
- static unsigned char dh1024_p[]={
- 0xB3,0x67,0x2E,0x3B,0x68,0xC5,0xDA,0x58,0x46,0xD6,0x2B,0xD3,
- 0x41,0x78,0x97,0xE4,0xE1,0x61,0x71,0x68,0xE6,0x0F,0x1D,0x78,
- 0x05,0xAA,0xF0,0xFF,0x30,0xDF,0xAC,0x49,0x7F,0xE0,0x90,0xFE,
- 0xB9,0x56,0x4E,0x3F,0xE2,0x98,0x8A,0xED,0xF5,0x28,0x39,0xEF,
- 0x2E,0xA6,0xB7,0x67,0xB2,0x43,0xE4,0x53,0xF8,0xEB,0x2C,0x1F,
- 0x06,0x77,0x3A,0x6F,0x62,0x98,0xC1,0x3B,0xF7,0xBA,0x4D,0x93,
- 0xF7,0xEB,0x5A,0xAD,0xC5,0x5F,0xF0,0xB7,0x24,0x35,0x81,0xF7,
- 0x7F,0x1F,0x24,0xC0,0xDF,0xD3,0xD8,0x40,0x72,0x7E,0xF3,0x19,
- 0x2B,0x26,0x27,0xF4,0xB6,0xB3,0xD4,0x7D,0x08,0x23,0xBE,0x68,
- 0x2B,0xCA,0xB4,0x46,0xA8,0x9E,0xDD,0x6C,0x3D,0x75,0xA6,0x48,
- 0xF7,0x44,0x43,0xBF,0x91,0xC2,0xB4,0x49,
+static DH *get_dh2048(void)
+{
+ static unsigned char dh2048_p[]={
+ 0xE7,0x36,0x28,0x3B,0xE4,0xC3,0x32,0x1C,0x01,0xC3,0x67,0xD6,
+ 0xF5,0xF3,0xDA,0xDC,0x71,0xC0,0x42,0x8B,0xE6,0xEB,0x8D,0x80,
+ 0x35,0x7F,0x09,0x45,0x30,0xE5,0xB2,0x92,0x81,0x3F,0x08,0xCD,
+ 0x36,0x5E,0x19,0x83,0x62,0xCC,0xAE,0x9B,0x81,0x66,0x24,0xEE,
+ 0x16,0x6F,0xA9,0x9E,0xF4,0x82,0x1B,0xDD,0x46,0xC7,0x33,0x5D,
+ 0xF4,0xCA,0xE6,0x8F,0xFC,0xD4,0xD8,0x58,0x94,0x24,0x5D,0xFF,
+ 0x0A,0xE8,0xEF,0x3D,0xCE,0xBB,0x50,0x94,0xE0,0x5F,0xE8,0x41,
+ 0xC3,0x35,0x30,0x37,0xD5,0xCB,0x8F,0x3D,0x95,0x15,0x1A,0x77,
+ 0x42,0xB2,0x06,0x86,0xF6,0x09,0x66,0x0E,0x9A,0x25,0x94,0x3E,
+ 0xD2,0x04,0x25,0x25,0x1D,0x23,0xEB,0xDC,0x4D,0x0C,0x83,0x28,
+ 0x2E,0x15,0x81,0x2D,0xC1,0xAF,0x8D,0x36,0x64,0xE3,0x9A,0x83,
+ 0x78,0xC2,0x8D,0xC0,0x9D,0xD9,0x3A,0x1C,0xC5,0x2B,0x50,0x68,
+ 0x07,0xA9,0x4B,0x8C,0x07,0x57,0xD6,0x15,0x03,0x4E,0x9E,0x01,
+ 0xF2,0x6F,0x35,0xAC,0x26,0x9C,0x92,0x68,0x61,0x13,0xFB,0x01,
+ 0xBA,0x22,0x36,0x01,0x55,0xB6,0x62,0xD9,0xB2,0x98,0xCE,0x5D,
+ 0x4B,0xA5,0x41,0xD6,0xE5,0x70,0x78,0x12,0x1F,0x64,0xB6,0x6F,
+ 0xB0,0x91,0x51,0x91,0x92,0xC0,0x94,0x3A,0xD1,0x28,0x4D,0x30,
+ 0x84,0x3E,0xE4,0xE4,0x7F,0x47,0x89,0xB1,0xB6,0x8C,0x8E,0x0E,
+ 0x26,0xDB,0xCD,0x17,0x07,0x2A,0x21,0x7A,0xCC,0x68,0xE8,0x57,
+ 0x94,0x9E,0x59,0x61,0xEC,0x20,0x34,0x26,0x0D,0x66,0x44,0xEB,
+ 0x6F,0x02,0x58,0xE2,0xED,0xF6,0xF3,0x1B,0xBF,0x9E,0x45,0x52,
+ 0x5A,0x49,0xA1,0x5B,
};
- static unsigned char dh1024_g[]={
- 0x5F,0x37,0xB5,0x80,0x4D,0xB4,0xC4,0xB2,0x37,0x12,0xD5,0x2F,
- 0x56,0x81,0xB0,0xDF,0x3D,0x27,0xA2,0x54,0xE7,0x14,0x65,0x2D,
- 0x72,0xA8,0x97,0xE0,0xA9,0x4A,0x09,0x5E,0x89,0xBE,0x34,0x9A,
- 0x90,0x98,0xC1,0xE8,0xBB,0x01,0x2B,0xC2,0x74,0x74,0x90,0x59,
- 0x0B,0x72,0x62,0x5C,0xFD,0x49,0x63,0x4B,0x38,0x91,0xF1,0x7F,
- 0x13,0x25,0xEB,0x52,0x50,0x47,0xA2,0x8C,0x32,0x28,0x42,0xAC,
- 0xBD,0x7A,0xCC,0x58,0xBE,0x36,0xDA,0x6A,0x24,0x06,0xC7,0xF1,
- 0xDA,0x8D,0x8A,0x3B,0x03,0xFA,0x6F,0x25,0xE5,0x20,0xA7,0xD6,
- 0x6F,0x74,0x61,0x53,0x14,0x81,0x29,0x04,0xB5,0x61,0x12,0x53,
- 0xA3,0xD6,0x09,0x98,0x0C,0x8F,0x1C,0xBB,0xD7,0x1C,0x2C,0xEE,
- 0x56,0x4B,0x74,0x8F,0x4A,0xF8,0xA9,0xD5,
+ static unsigned char dh2048_g[]={
+ 0x02,
};
- DH *dh;
-
- if ((dh=DH_new()) == NULL) return(NULL);
- dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
- dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
- if ((dh->p == NULL) || (dh->g == NULL))
- { DH_free(dh); return(NULL); }
- dh->length = 160;
- return(dh);
+ DH *dh = NULL;
+ BIGNUM *p = NULL, *g = NULL;
+
+ dh = DH_new();
+ p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
+ g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
+ if (!dh || !p || !g)
+ goto err;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
+ dh->p = p;
+ dh->g = g;
+#else
+ if (!DH_set0_pqg(dh, p, NULL, g))
+ goto err;
+#endif
+ return dh;
+err:
+ if (p)
+ BN_free(p);
+ if (g)
+ BN_free(g);
+ if (dh)
+ DH_free(dh);
+ return NULL;
}
#endif /* SPLINT */
@@ -225,14 +245,16 @@ daemon_remote_create(struct config_file* cfg)
/* No certificates are requested */
if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL")) {
log_crypto_err("Failed to set aNULL cipher list");
+ daemon_remote_delete(rc);
return NULL;
}
/* Since we have no certificates and hence no source of
* DH params, let's generate and set them
*/
- if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh1024())) {
+ if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh2048())) {
log_crypto_err("Wanted to set DH param, but failed");
+ daemon_remote_delete(rc);
return NULL;
}
return rc;
@@ -359,8 +381,12 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
if(fd != -1) {
#ifdef HAVE_CHOWN
if (cfg->username && cfg->username[0] &&
- cfg_uid != (uid_t)-1)
- chown(ip, cfg_uid, cfg_gid);
+ cfg_uid != (uid_t)-1) {
+ if(chown(ip, cfg_uid, cfg_gid) == -1)
+ log_err("cannot chown %u.%u %s: %s",
+ (unsigned)cfg_uid, (unsigned)cfg_gid,
+ ip, strerror(errno));
+ }
chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
#else
(void)cfg;
@@ -389,7 +415,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
/* open fd */
fd = create_tcp_accept_sock(res, 1, &noproto, 0,
- cfg->ip_transparent, 0);
+ cfg->ip_transparent, 0, cfg->ip_freebind);
freeaddrinfo(res);
}
diff --git a/contrib/unbound/daemon/remote.h b/contrib/unbound/daemon/remote.h
index b25bfb1..190286d 100644
--- a/contrib/unbound/daemon/remote.h
+++ b/contrib/unbound/daemon/remote.h
@@ -56,8 +56,8 @@ struct comm_reply;
struct comm_point;
struct daemon_remote;
-/** number of seconds timeout on incoming remote control handshake */
-#define REMOTE_CONTROL_TCP_TIMEOUT 120
+/** number of milliseconds timeout on incoming remote control handshake */
+#define REMOTE_CONTROL_TCP_TIMEOUT 120000
/**
* a busy control command connection, SSL state
diff --git a/contrib/unbound/daemon/unbound.c b/contrib/unbound/daemon/unbound.c
index a981f49..73e9fcb 100644
--- a/contrib/unbound/daemon/unbound.c
+++ b/contrib/unbound/daemon/unbound.c
@@ -57,6 +57,7 @@
#include "util/data/msgreply.h"
#include "util/module.h"
#include "util/net_help.h"
+#include "util/ub_event.h"
#include <signal.h>
#include <fcntl.h>
#include <openssl/crypto.h>
@@ -77,22 +78,6 @@
#include <login_cap.h>
#endif
-#ifdef USE_MINI_EVENT
-# ifdef USE_WINSOCK
-# include "util/winsock_event.h"
-# else
-# include "util/mini_event.h"
-# endif
-#else
-# ifdef HAVE_EVENT_H
-# include <event.h>
-# else
-# include "event2/event.h"
-# include "event2/event_struct.h"
-# include "event2/event_compat.h"
-# endif
-#endif
-
#ifdef UB_ON_WINDOWS
# include "winrc/win_svc.h"
#endif
@@ -107,59 +92,14 @@
void* unbound_start_brk = 0;
#endif
-#if !defined(HAVE_EVENT_BASE_GET_METHOD) && (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP))
-static const char* ev_backend2str(int b)
-{
- switch(b) {
- case EVBACKEND_SELECT: return "select";
- case EVBACKEND_POLL: return "poll";
- case EVBACKEND_EPOLL: return "epoll";
- case EVBACKEND_KQUEUE: return "kqueue";
- case EVBACKEND_DEVPOLL: return "devpoll";
- case EVBACKEND_PORT: return "evport";
- }
- return "unknown";
-}
-#endif
-
-/** get the event system in use */
-static void get_event_sys(const char** n, const char** s, const char** m)
-{
-#ifdef USE_WINSOCK
- *n = "event";
- *s = "winsock";
- *m = "WSAWaitForMultipleEvents";
-#elif defined(USE_MINI_EVENT)
- *n = "mini-event";
- *s = "internal";
- *m = "select";
-#else
- struct event_base* b;
- *s = event_get_version();
-# ifdef HAVE_EVENT_BASE_GET_METHOD
- *n = "libevent";
- b = event_base_new();
- *m = event_base_get_method(b);
-# elif defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
- *n = "libev";
- b = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
- *m = ev_backend2str(ev_backend((struct ev_loop*)b));
-# else
- *n = "unknown";
- *m = "not obtainable";
- b = NULL;
-# endif
-# ifdef HAVE_EVENT_BASE_FREE
- event_base_free(b);
-# endif
-#endif
-}
-
/** print usage. */
-static void usage()
+static void usage(void)
{
const char** m;
const char *evnm="event", *evsys="", *evmethod="";
+ time_t t;
+ struct timeval now;
+ struct ub_event_base* base;
printf("usage: unbound [options]\n");
printf(" start unbound daemon DNS resolver.\n");
printf("-h this help\n");
@@ -173,11 +113,16 @@ static void usage()
printf(" service - used to start from services control panel\n");
#endif
printf("Version %s\n", PACKAGE_VERSION);
- get_event_sys(&evnm, &evsys, &evmethod);
+ base = ub_default_event_base(0,&t,&now);
+ ub_get_event_sys(base, &evnm, &evsys, &evmethod);
printf("linked libs: %s %s (it uses %s), %s\n",
evnm, evsys, evmethod,
#ifdef HAVE_SSL
+# ifdef SSLEAY_VERSION
SSLeay_version(SSLEAY_VERSION)
+# else
+ OpenSSL_version(OPENSSL_VERSION)
+# endif
#elif defined(HAVE_NSS)
NSS_GetVersion()
#elif defined(HAVE_NETTLE)
@@ -190,6 +135,7 @@ static void usage()
printf("\n");
printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
+ ub_event_base_free(base);
}
#ifndef unbound_testbound
@@ -230,7 +176,7 @@ checkrlimits(struct config_file* cfg)
struct rlimit rlim;
if(total > 1024 &&
- strncmp(event_get_version(), "mini-event", 10) == 0) {
+ strncmp(ub_event_get_version(), "mini-event", 10) == 0) {
log_warn("too many file descriptors requested. The builtin"
"mini-event cannot handle more than 1024. Config "
"for less fds or compile with libevent");
@@ -244,7 +190,7 @@ checkrlimits(struct config_file* cfg)
total = 1024;
}
if(perthread > 64 &&
- strncmp(event_get_version(), "winsock-event", 13) == 0) {
+ strncmp(ub_event_get_version(), "winsock-event", 13) == 0) {
log_err("too many file descriptors requested. The winsock"
" event handler cannot handle more than 64 per "
" thread. Config for less fds");
@@ -602,7 +548,9 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
log_warn("unable to initgroups %s: %s",
cfg->username, strerror(errno));
# endif /* HAVE_INITGROUPS */
+# ifdef HAVE_ENDPWENT
endpwent();
+# endif
#ifdef HAVE_SETRESGID
if(setresgid(cfg_gid,cfg_gid,cfg_gid) != 0)
diff --git a/contrib/unbound/daemon/worker.c b/contrib/unbound/daemon/worker.c
index a74931f..70d07ba 100644
--- a/contrib/unbound/daemon/worker.c
+++ b/contrib/unbound/daemon/worker.c
@@ -483,7 +483,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
qinfo->qname_len, qinfo->qtype, qinfo->qclass,
worker->scratchpad, &msg, timenow);
if(!dp) { /* no delegation, need to reprime */
- regional_free_all(worker->scratchpad);
return 0;
}
if(must_validate) {
@@ -491,7 +490,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
case sec_status_unchecked:
/* some rrsets have not been verified yet, go and
* let validator do that */
- regional_free_all(worker->scratchpad);
return 0;
case sec_status_bogus:
/* some rrsets are bogus, reply servfail */
@@ -499,9 +497,10 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
+ if(!edns_opt_inplace_reply(edns, worker->scratchpad))
+ return 0;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&msg->qinfo, id, flags, edns);
- regional_free_all(worker->scratchpad);
if(worker->stats.extended) {
worker->stats.ans_bogus++;
worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL]++;
@@ -527,6 +526,8 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
+ if(!edns_opt_inplace_reply(edns, worker->scratchpad))
+ return 0;
msg->rep->flags |= BIT_QR|BIT_RA;
if(!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags,
repinfo->c->buffer, 0, 1, worker->scratchpad,
@@ -534,7 +535,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&msg->qinfo, id, flags, edns);
}
- regional_free_all(worker->scratchpad);
if(worker->stats.extended) {
if(secure) worker->stats.ans_secure++;
server_stats_insrcode(&worker->stats, repinfo->c->buffer);
@@ -574,7 +574,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
bail_out:
rrset_array_unlock_touch(worker->env.rrset_cache,
worker->scratchpad, rep->ref, rep->rrset_count);
- regional_free_all(worker->scratchpad);
return 0;
}
}
@@ -585,11 +584,12 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
+ if(!edns_opt_inplace_reply(edns, worker->scratchpad))
+ return 0;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, id, flags, edns);
rrset_array_unlock_touch(worker->env.rrset_cache,
worker->scratchpad, rep->ref, rep->rrset_count);
- regional_free_all(worker->scratchpad);
if(worker->stats.extended) {
worker->stats.ans_bogus ++;
worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL] ++;
@@ -616,6 +616,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
+ if(!edns_opt_inplace_reply(edns, worker->scratchpad))
+ return 0;
if(!reply_info_answer_encode(qinfo, rep, id, flags,
repinfo->c->buffer, timenow, 1, worker->scratchpad,
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
@@ -626,7 +628,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
* is bad while holding locks. */
rrset_array_unlock_touch(worker->env.rrset_cache, worker->scratchpad,
rep->ref, rep->rrset_count);
- regional_free_all(worker->scratchpad);
if(worker->stats.extended) {
if(secure) worker->stats.ans_secure++;
server_stats_insrcode(&worker->stats, repinfo->c->buffer);
@@ -658,9 +659,11 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
* @param pkt: buffer
* @param str: string to put into text record (<255).
* @param edns: edns reply information.
+ * @param worker: worker with scratch region.
*/
static void
-chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns)
+chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
+ struct worker* worker)
{
size_t len = strlen(str);
unsigned int rd = LDNS_RD_WIRE(sldns_buffer_begin(pkt));
@@ -689,6 +692,8 @@ chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns)
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->bits &= EDNS_DO;
+ if(!edns_opt_inplace_reply(edns, worker->scratchpad))
+ edns->opt_list = NULL;
attach_edns_record(pkt, edns);
}
@@ -718,13 +723,13 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
char buf[MAXHOSTNAMELEN+1];
if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
buf[MAXHOSTNAMELEN] = 0;
- chaos_replystr(pkt, buf, edns);
+ chaos_replystr(pkt, buf, edns, w);
} else {
log_err("gethostname: %s", strerror(errno));
- chaos_replystr(pkt, "no hostname", edns);
+ chaos_replystr(pkt, "no hostname", edns, w);
}
}
- else chaos_replystr(pkt, cfg->identity, edns);
+ else chaos_replystr(pkt, cfg->identity, edns, w);
return 1;
}
if(query_dname_compare(qinfo->qname,
@@ -735,8 +740,8 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
if(cfg->hide_version)
return 0;
if(cfg->version==NULL || cfg->version[0]==0)
- chaos_replystr(pkt, PACKAGE_STRING, edns);
- else chaos_replystr(pkt, cfg->version, edns);
+ chaos_replystr(pkt, PACKAGE_STRING, edns, w);
+ else chaos_replystr(pkt, cfg->version, edns, w);
return 1;
}
return 0;
@@ -768,6 +773,8 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
+ sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
+ sldns_buffer_flip(c->buffer);
return 1;
}
@@ -799,6 +806,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
struct query_info qinfo;
struct edns_data edns;
enum acl_access acl;
+ struct acl_addr* acladdr;
int rc = 0;
if(error != NETEVENT_NOERROR) {
@@ -811,8 +819,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, c->type,
c->buffer);
#endif
- acl = acl_list_lookup(worker->daemon->acl, &repinfo->addr,
+ acladdr = acl_addr_lookup(worker->daemon->acl, &repinfo->addr,
repinfo->addrlen);
+ acl = acl_get_control(acladdr);
if((ret=deny_refuse_all(c, acl, worker, repinfo)) != -1)
{
if(ret == 1)
@@ -865,7 +874,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
goto send_reply;
}
- if((ret=parse_edns_from_pkt(c->buffer, &edns)) != 0) {
+ if((ret=parse_edns_from_pkt(c->buffer, &edns, worker->scratchpad)) != 0) {
struct edns_data reply_edns;
verbose(VERB_ALGO, "worker parse edns: formerror.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
@@ -876,6 +885,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
error_encode(c->buffer, ret, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), &reply_edns);
+ regional_free_all(worker->scratchpad);
server_stats_insrcode(&worker->stats, c->buffer);
goto send_reply;
}
@@ -884,12 +894,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
edns.edns_version = EDNS_ADVERTISED_VERSION;
edns.udp_size = EDNS_ADVERTISED_SIZE;
edns.bits &= EDNS_DO;
+ edns.opt_list = NULL;
verbose(VERB_ALGO, "query with bad edns version.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
attach_edns_record(c->buffer, &edns);
+ regional_free_all(worker->scratchpad);
goto send_reply;
}
if(edns.edns_present && edns.udp_size < NORMAL_UDP_SIZE &&
@@ -918,6 +930,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
sldns_buffer_write_at(c->buffer, 4,
(uint8_t*)"\0\0\0\0\0\0\0\0", 8);
sldns_buffer_flip(c->buffer);
+ regional_free_all(worker->scratchpad);
goto send_reply;
}
if(worker->stats.extended)
@@ -928,10 +941,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
&edns, c->buffer)) {
server_stats_insrcode(&worker->stats, c->buffer);
+ regional_free_all(worker->scratchpad);
goto send_reply;
}
if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns,
- c->buffer, worker->scratchpad, repinfo)) {
+ c->buffer, worker->scratchpad, repinfo,
+ acladdr->taglist, acladdr->taglen, acladdr->tag_actions,
+ acladdr->tag_actions_size, acladdr->tag_datas,
+ acladdr->tag_datas_size, worker->daemon->cfg->tagname,
+ worker->daemon->cfg->num_tags)) {
regional_free_all(worker->scratchpad);
if(sldns_buffer_limit(c->buffer) == 0) {
comm_point_drop_reply(repinfo);
@@ -945,6 +963,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
* might need to bail out based on ACLs now. */
if((ret=deny_refuse_non_local(c, acl, worker, repinfo)) != -1)
{
+ regional_free_all(worker->scratchpad);
if(ret == 1)
goto send_reply;
return ret;
@@ -961,6 +980,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
sldns_buffer_flip(c->buffer);
+ regional_free_all(worker->scratchpad);
server_stats_insrcode(&worker->stats, c->buffer);
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->addr, repinfo->addrlen);
@@ -984,9 +1004,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
sldns_buffer_read_u16_at(c->buffer, 2),
repinfo, leeway);
rc = 0;
+ regional_free_all(worker->scratchpad);
goto send_reply_rc;
}
lock_rw_unlock(&e->lock);
+ regional_free_all(worker->scratchpad);
goto send_reply;
}
verbose(VERB_ALGO, "answer from the cache failed");
@@ -997,6 +1019,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
&edns)) {
+ regional_free_all(worker->scratchpad);
goto send_reply;
}
verbose(VERB_ALGO, "answer norec from cache -- "
@@ -1017,6 +1040,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
mesh_new_client(worker->env.mesh, &qinfo,
sldns_buffer_read_u16_at(c->buffer, 2),
&edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer));
+ regional_free_all(worker->scratchpad);
worker_mem_report(worker, NULL);
return 0;
@@ -1355,8 +1379,9 @@ worker_delete(struct worker* worker)
struct outbound_entry*
worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec,
- int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, struct module_qstate* q)
+ int nocaps, struct edns_option* opt_list,
+ struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
+ size_t zonelen, struct module_qstate* q)
{
struct worker* worker = q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@@ -1366,8 +1391,8 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
e->qstate = q;
e->qsent = outnet_serviced_query(worker->back, qname,
qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps,
- q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
- addrlen, zone, zonelen, worker_handle_service_reply, e,
+ q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, opt_list,
+ addr, addrlen, zone, zonelen, worker_handle_service_reply, e,
worker->back->udp_buff);
if(!e->qsent) {
return NULL;
@@ -1412,7 +1437,8 @@ struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
+ struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{
diff --git a/contrib/unbound/dns64/dns64.c b/contrib/unbound/dns64/dns64.c
index 0de3f66..5fa2096 100644
--- a/contrib/unbound/dns64/dns64.c
+++ b/contrib/unbound/dns64/dns64.c
@@ -521,13 +521,14 @@ handle_event_moddone(struct module_qstate* qstate, int id)
* - An internal query.
* - A query for a record type other than AAAA.
* - CD FLAG was set on querier
- * - An AAAA query for which an error was returned.
+ * - An AAAA query for which an error was returned.(qstate.return_rcode)
+ * -> treated as servfail thus synthesize (sec 5.1.3 6147), thus
+ * synthesize in (sec 5.1.2 of RFC6147).
* - A successful AAAA query with an answer.
*/
if ( (enum dns64_qstate)qstate->minfo[id] == DNS64_INTERNAL_QUERY
|| qstate->qinfo.qtype != LDNS_RR_TYPE_AAAA
|| (qstate->query_flags & BIT_CD)
- || qstate->return_rcode != LDNS_RCODE_NOERROR
|| (qstate->return_msg &&
qstate->return_msg->rep &&
reply_find_answer_rrset(&qstate->qinfo,
@@ -871,7 +872,7 @@ static struct module_func_block dns64_block = {
* Function for returning the above function block.
*/
struct module_func_block *
-dns64_get_funcblock()
+dns64_get_funcblock(void)
{
return &dns64_block;
}
diff --git a/contrib/unbound/dnstap/dnstap.c b/contrib/unbound/dnstap/dnstap.c
index 8c9c4ca..6df2fef 100644
--- a/contrib/unbound/dnstap/dnstap.c
+++ b/contrib/unbound/dnstap/dnstap.c
@@ -475,7 +475,7 @@ dt_msg_send_outside_response(struct dt_env *env,
return;
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE);
} else {
- if (!env->log_resolver_query_messages)
+ if (!env->log_resolver_response_messages)
return;
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE);
}
diff --git a/contrib/unbound/doc/Changelog b/contrib/unbound/doc/Changelog
index 6bcc32a..039eade 100644
--- a/contrib/unbound/doc/Changelog
+++ b/contrib/unbound/doc/Changelog
@@ -1,3 +1,367 @@
+20 September 2016: Wouter
+ - iana portlist update.
+ - Fix #835: fix --disable-dsa with nettle verify.
+ - tag for 1.5.10rc1 release.
+
+15 September 2016: Wouter
+ - Fix 883: error for duplicate local zone entry.
+ - Test for openssl init_crypto and init_ssl functions.
+
+15 September 2016: Ralph
+ - fix potential memory leak in daemon/remote.c and nullpointer
+ dereference in validator/autotrust.
+ - iana portlist update.
+
+13 September 2016: Wouter
+ - Silenced flex-generated sign-unsigned warning print with gcc
+ diagnostic pragma.
+ - Fix for new splint on FreeBSD. Fix cast for sockaddr_un.sun_len.
+
+9 September 2016: Wouter
+ - Fix #831: workaround for spurious fread_chk warning against petal.c
+
+5 September 2016: Ralph
+ - Take configured minimum TTL into consideration when reducing TTL
+ to original TTL from RRSIG.
+
+5 September 2016: Wouter
+ - Fix #829: doc of sldns_wire2str_rdata_buf() return value has an
+ off-by-one typo, from Jinmei Tatuya (Infoblox).
+ - Fix incomplete prototypes reported by Dag-Erling Smørgrav.
+ - Fix #828: missing type in access-control-tag-action redirect results
+ in NXDOMAIN.
+
+2 September 2016: Wouter
+ - Fix compile with openssl 1.1.0 with api=1.1.0.
+
+1 September 2016: Wouter
+ - RFC 7958 is now out, updated docs for unbound-anchor.
+ - Fix for compile without warnings with openssl 1.1.0.
+ - Fix #826: Fix refuse_non_local could result in a broken response.
+ - iana portlist update.
+
+29 August 2016: Wouter
+ - Fix #777: OpenSSL 1.1.0 compatibility, patch from Sebastian A.
+ Siewior.
+ - Add default root hints for IPv6 E.ROOT-SERVERS.NET, 2001:500:a8::e.
+
+25 August 2016: Ralph
+ - Clarify local-zone-override entry in unbound.conf.5
+
+25 August 2016: Wouter
+ - 64bit build option for makedist windows compile, -w64.
+
+24 August 2016: Ralph
+ - Fix #820: set sldns_str2wire_rr_buf() dual meaning len parameter
+ in each iteration in find_tag_datas().
+ - unbound.conf.5 entries for define-tag, access-control-tag,
+ access-control-tag-action, access-control-tag-data, local-zone-tag,
+ and local-zone-override.
+
+23 August 2016: Wouter
+ - Fix #804: unbound stops responding after outage. Fixes queries
+ that attempt to wait for an empty list of subqueries.
+ - Fix #804: lower num_target_queries for iterator also for failed
+ lookups.
+
+8 August 2016: Wouter
+ - Note that OPENPGPKEY type is RFC 7929.
+
+4 August 2016: Wouter
+ - Fix #807: workaround for possible some "unused" function parameters
+ in test code, from Jinmei Tatuya.
+
+3 August 2016: Wouter
+ - use sendmsg instead of sendto for TFO.
+
+28 July 2016: Wouter
+ - Fix #806: wrong comment removed.
+
+26 July 2016: Wouter
+ - nicer ratelimit-below-domain explanation.
+
+22 July 2016: Wouter
+ - Fix #801: missing error condition handling in
+ daemon_create_workers().
+ - Fix #802: workaround for function parameters that are "unused"
+ without log_assert.
+ - Fix #803: confusing (and incorrect) code comment in daemon_cleanup().
+
+20 July 2016: Wouter
+ - Fix typo in unbound.conf.
+
+18 July 2016: Wouter
+ - Fix #798: Client-side TCP fast open fails (Linux).
+
+14 July 2016: Wouter
+ - TCP Fast open patch from Sara Dickinson.
+ - Fixed unbound.doxygen for 1.8.11.
+
+7 July 2016: Wouter
+ - access-control-tag-data implemented. verbose(4) prints tag debug.
+
+5 July 2016: Wouter
+ - Fix dynamic link of anchor-update.exe on windows.
+ - Fix detect of mingw for MXE package build.
+ - Fixes for 64bit windows compile.
+ - Fix #788 for nettle 3.0: Failed to build with Nettle >= 3.0 and
+ --with-libunbound-only --with-nettle.
+
+4 July 2016: Wouter
+ - For #787: prefer-ip6 option for unbound.conf prefers to send
+ upstream queries to ipv6 servers.
+ - Fix #787: outgoing-interface netblock/64 ipv6 option to use linux
+ freebind to use 64bits of entropy for every query with random local
+ part.
+
+30 June 2016: Wouter
+ - Document always_transparent, always_refuse, always_nxdomain types.
+
+29 June 2016: Wouter
+ - Fix static compile on windows missing gdi32.
+
+28 June 2016: Wouter
+ - Create a pkg-config file for libunbound in contrib.
+
+27 June 2016: Wouter
+ - Fix #784: Build configure assumess that having getpwnam means there
+ is endpwent function available.
+ - Updated repository with newer flex and bison output.
+
+24 June 2016: Ralph
+ - Possibility to specify local-zone type for an acl/tag pair
+ - Possibility to specify (override) local-zone type for a source address
+ block
+16 June 2016: Ralph
+ - Decrease dp attempts at each QNAME minimisation iteration
+
+16 June 2016: Wouter
+ - Fix tcp timeouts in tv.usec.
+
+15 June 2016: Wouter
+ - TCP_TIMEOUT is specified in milliseconds.
+ - If more than half of tcp connections are in use, a shorter timeout
+ is used (200 msec, vs 2 minutes) to pressure tcp for new connects.
+
+14 June 2016: Ralph
+ - QNAME minimisation unit test for dropped QTYPE=A queries.
+
+14 June 2016: Wouter
+ - Fix 775: unbound-host and unbound-anchor crash on windows, ignore
+ null delete for wsaevent.
+ - Fix spelling in freebind option man page text.
+ - Fix windows link of ssl with crypt32.
+ - Fix 779: Union casting is non-portable.
+ - Fix 780: MAP_ANON not defined in HP-UX 11.31.
+ - Fix 781: prealloc() is an HP-UX system library call.
+
+13 June 2016: Ralph
+ - Use QTYPE=A for QNAME minimisation.
+ - Keep track of number of time-outs when performing QNAME minimisation.
+ Stop minimising when number of time-outs for a QNAME/QTYPE pair is
+ more than three.
+
+13 June 2016: Wouter
+ - Fix #778: unbound 1.5.9: -h segfault (null deref).
+ - Fix directory: fix for unbound-checkconf, it restores cwd.
+
+10 June 2016: Wouter
+ - And delete service.conf.shipped on uninstall.
+ - In unbound.conf directory: dir immediately changes to that directory,
+ so that include: file below that is relative to that directory.
+ With chroot, make the directory an absolute path inside chroot.
+ - keep debug symbols in windows build.
+ - do not delete service.conf on windows uninstall.
+ - document directory immediate fix and allow EXECUTABLE syntax in it
+ on windows.
+
+9 June 2016: Wouter
+ - Trunk is called 1.5.10 (with previous fixes already in there to 2
+ june).
+ - Revert fix for NetworkService account on windows due to breakage
+ it causes.
+ - Fix that windows install will not overwrite existing service.conf
+ file (and ignore gui config choices if it exists).
+
+7 June 2016: Ralph
+ - Lookup localzones by taglist from acl.
+ - Possibility to lookup local_zone, regardless the taglist.
+ - Added local_zone/taglist/acl unit test.
+
+7 June 2016: Wouter
+ - Fix #773: Non-standard Python location build failure with pyunbound.
+ - Improve threadsafety for openssl 0.9.8 ecdsa dnssec signatures.
+
+6 June 2016: Wouter
+ - Better help text from -h (from Ray Griffith).
+ - access-control-tag config directive.
+ - local-zone-override config directive.
+ - access-control-tag-action and access-control-tag-data config
+ directives.
+ - free acl-tags, acltag-action and acltag-data config lists during
+ initialisation to free up memory for more entries.
+
+3 June 2016: Wouter
+ - Fix to not ignore return value of chown() in daemon startup.
+
+2 June 2016: Wouter
+ - Fix libubound for edns optlist feature.
+ - Fix distinction between free and CRYPTO_free in dsa and ecdsa alloc.
+ - Fix #752: retry resource temporarily unavailable on control pipe.
+ - un-document localzone tags.
+ - tag for release 1.5.9rc1.
+ And this also became release 1.5.9.
+ - Fix (for 1.5.10): Fix unbound-anchor.exe file location defaults to
+ Program Files with (x86) appended.
+ - re-documented localzone tags in example.conf.
+
+31 May 2016: Wouter
+ - Fix windows service to be created run with limited rights, as a
+ network service account, from Mario Turschmann.
+ - compat strsep implementation.
+ - generic edns option parse and store code.
+ - and also generic edns options for upstream messages (and replies).
+ after parse use edns_opt_find(edns.opt_list, LDNS_EDNS_NSID),
+ to insert use edns_opt_append(edns, region, code, len, bindata) on
+ the opt_list passed to send_query, or in edns_opt_inplace_reply.
+
+30 May 2016: Wouter
+ - Fix time in case answer comes from cache in ub_resolve_event().
+ - Attempted fix for #765: _unboundmodule missing for python3.
+
+27 May 2016: Wouter
+ - Fix #770: Small subgroup attack on DH used in unix pipe on localhost
+ if unbound control uses a unix local named pipe.
+ - Document write permission to directory of trust anchor needed.
+ - Fix #768: Unbound Service Sometimes Can Not Shutdown
+ Completely, WER Report Shown Up. Close handle before closing WSA.
+
+26 May 2016: Wouter
+ - Updated patch from Charles Walker.
+
+24 May 2016: Wouter
+ - disable-dnssec-lame-check config option from Charles Walker.
+ - remove memory leak from lame-check patch.
+ - iana portlist update.
+
+23 May 2016: Wouter
+ - Fix #767: Reference to an expired Internet-Draft in
+ harden-below-nxdomain documentation.
+
+20 May 2016: Ralph
+ - No QNAME minimisation fall-back for NXDOMAIN answers from DNSSEC
+ signed zones.
+ - iana portlist update.
+
+19 May 2016: Wouter
+ - Fix #766: dns64 should synthesize results on timeout/errors.
+
+18 May 2016: Wouter
+ - Fix #761: DNSSEC LAME false positive resolving nic.club.
+
+17 May 2016: Wouter
+ - trunk updated with output of flex 2.6.0.
+
+6 May 2016: Wouter
+ - Fix memory leak in out-of-memory conditions of local zone add.
+
+29 April 2016: Wouter
+ - Fix sldns with static checking fixes copied from getdns.
+
+28 April 2016: Wouter
+ - Fix #759: 0x20 capsforid no longer checks type PTR, for
+ compatibility with cisco dns guard. This lowers false positives.
+
+18 April 2016: Wouter
+ - Fix some malformed reponses to edns queries get fallback to nonedns.
+
+15 April 2016: Wouter
+ - cachedb module event handling design.
+
+14 April 2016: Wouter
+ - cachedb module framework (empty).
+ - iana portlist update.
+
+12 April 2016: Wouter
+ - Fix #753: document dump_requestlist is for first thread.
+
+24 March 2016: Wouter
+ - Document permit-small-holddown for 5011 debug.
+ - Fix #749: unbound-checkconf gets SIGSEGV when use against a
+ malformatted conf file.
+
+23 March 2016: Wouter
+ - OpenSSL 1.1.0 portability, --disable-dsa configure option.
+
+21 March 2016: Wouter
+ - Fix compile of getentropy_linux for SLES11 servicepack 4.
+ - Fix dnstap-log-resolver-response-messages, from Nikolay Edigaryev.
+ - Fix test for openssl to use HMAC_Update for 1.1.0.
+ - acx_nlnetlabs.m4 to v33, with HMAC_Update.
+ - acx_nlnetlabs.m4 to v34, with -ldl -pthread test for libcrypto.
+ - ERR_remove_state deprecated since openssl 1.0.0.
+ - OPENSSL_config is deprecated, removing.
+
+18 March 2016: Ralph
+ - Validate QNAME minimised NXDOMAIN responses.
+ - If QNAME minimisation is enabled, do cache lookup for QTYPE NS in
+ harden-below-nxdomain.
+
+17 March 2016: Ralph
+ - Limit number of QNAME minimisation iterations.
+
+17 March 2016: Wouter
+ - Fix #746: Fix unbound sets CD bit on all forwards.
+ If no trust anchors, it'll not set CD bit when forwarding to another
+ server. If a trust anchor, no CD bit on the first attempt to a
+ forwarder, but CD bit thereafter on repeated attempts to get DNSSEC.
+ - iana portlist update.
+
+16 March 2016: Wouter
+ - Fix ip-transparent for ipv6 on FreeBSD, thanks to Nick Hibma.
+ - Fix ip-transparent for tcp on freebsd.
+
+15 March 2016: Wouter
+ - ip_freebind: yesno option in unbound.conf sets IP_FREEBIND for
+ binding to an IP address while the interface or address is down.
+
+14 March 2016: Wouter
+ - Fix warnings in ifdef corner case, older or unknown libevent.
+ - Fix compile for ub_event code with older libev.
+
+11 March 2016: Wouter
+ - Remove warning about unused parameter in event_pluggable.c.
+ - Fix libev usage of dispatch return value.
+ - No side effects in tolower() call, in case it is a macro.
+ - For test put free in pluggable api in parenthesis.
+
+10 March 2016: Wouter
+ - Fixup backend2str for libev.
+
+09 March 2016: Willem
+ - User defined pluggable event API for libunbound
+ - Fixup of compile fix for pluggable event API from P.Y. Adi
+ Prasaja.
+
+09 March 2016: Wouter
+ - Updated configure and ltmain.sh.
+ - Updated L root IPv6 address.
+
+07 March 2016: Wouter
+ - Fix #747: assert in outnet_serviced_query_stop.
+ - iana ports fetched via https.
+ - iana portlist update.
+
+03 March 2016: Wouter
+ - configure tests for the weak attribute support by the compiler.
+
+02 March 2016: Wouter
+ - 1.5.8 release tag
+ - trunk contains 1.5.9 in development.
+ - iana portlist update.
+ - Fix #745: unbound.py - idn2dname throws UnicodeError when idnname
+ contains trailing dot.
+
24 February 2016: Wouter
- Fix OpenBSD asynclook lock free that gets used later (fix test code).
- Fix that NSEC3 negative cache is used when there is no salt.
diff --git a/contrib/unbound/doc/README b/contrib/unbound/doc/README
index c87c62e..66e2f34 100644
--- a/contrib/unbound/doc/README
+++ b/contrib/unbound/doc/README
@@ -1,4 +1,4 @@
-README for Unbound 1.5.8
+README for Unbound 1.5.10
Copyright 2007 NLnet Labs
http://unbound.net
diff --git a/contrib/unbound/doc/example.conf b/contrib/unbound/doc/example.conf
index 3b2267d..80c0f3e 100644
--- a/contrib/unbound/doc/example.conf
+++ b/contrib/unbound/doc/example.conf
@@ -1,7 +1,7 @@
#
# Example configuration file.
#
-# See unbound.conf(5) man page, version 1.5.8.
+# See unbound.conf(5) man page, version 1.5.10.
#
# this is a comment.
@@ -52,6 +52,15 @@ server:
# outgoing-interface: 192.0.2.153
# outgoing-interface: 2001:DB8::5
# outgoing-interface: 2001:DB8::6
+
+ # Specify a netblock to use remainder 64 bits as random bits for
+ # upstream queries. Uses freebind option (Linux).
+ # outgoing-interface: 2001:DB8::/64
+ # Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
+ # And: ip -6 route add local 2001:db8::/64 dev lo
+ # And set prefer-ip6: yes to use the ip6 randomness from a netblock.
+ # Set this to yes to prefer ipv6 upstream servers over ipv4.
+ # prefer-ip6: no
# number of ports to allocate per thread, determines the size of the
# port range that can be open simultaneously. About double the
@@ -93,6 +102,11 @@ server:
# (uses IP_BINDANY on FreeBSD).
# ip-transparent: no
+ # use IP_FREEBIND so the interface: addresses can be non-local
+ # and you can bind to nonexisting IPs and interfaces that are down.
+ # Linux only. On Linux you also have ip-transparent that is similar.
+ # ip-freebind: no
+
# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
# is set with msg-buffer-size). 1480 can solve fragmentation (timeouts).
# edns-buffer-size: 4096
@@ -157,6 +171,10 @@ server:
# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
# infra-cache-numhosts: 10000
+
+ # define a number of tags here, use with local-zone, access-control.
+ # repeat the define-tag statement to add additional tags.
+ # define-tag: "tag1 tag2 tag3"
# Enable IPv4, "yes" or "no".
# do-ip4: yes
@@ -198,6 +216,20 @@ server:
# access-control: ::1 allow
# access-control: ::ffff:127.0.0.1 allow
+ # tag access-control with list of tags (in "" with spaces between)
+ # Clients using this access control element use localzones that
+ # are tagged with one of these tags.
+ # access-control-tag: 192.0.2.0/24 "tag2 tag3"
+
+ # set action for particular tag for given access control element
+ # if you have multiple tag values, the tag used to lookup the action
+ # is the first tag match between access-control-tag and local-zone-tag
+ # where "first" comes from the order of the define-tag values.
+ # access-control-tag-action: 192.0.2.0/24 tag3 refuse
+
+ # set redirect data for particular tag for access control element
+ # access-control-tag-data: 192.0.2.0/24 tag2 "A 127.0.0.1"
+
# if given, a chroot(2) is done to the given directory.
# i.e. you can chroot to the working directory, for example,
# for extra security, but make sure all files are in that directory.
@@ -231,6 +263,8 @@ server:
# the working directory. The relative files in this config are
# relative to this directory. If you give "" the working directory
# is not changed.
+ # If you give a server: directory: dir before include: file statements
+ # then those includes can be relative to the working directory.
# directory: "/var/unbound"
# the log file, "" means log to stderr.
@@ -317,6 +351,7 @@ server:
# Domains (and domains in them) without support for dns-0x20 and
# the fallback fails because they keep sending different answers.
# caps-whitelist: "licdn.com"
+ # caps-whitelist: "senderbase.org"
# Enforce privacy of these addresses. Strips them away from answers.
# It may cause DNSSEC validation to additionally mark it as bogus.
@@ -364,6 +399,9 @@ server:
# into response messages when those sections are not required.
# minimal-responses: no
+ # true to disable DNSSEC lameness check in iterator.
+ # disable-dnssec-lame-check: no
+
# module configuration of the server. A string with identifiers
# separated by spaces. Syntax: "[dns64] [validator] iterator"
# module-config: "validator iterator"
@@ -459,7 +497,8 @@ server:
# If the value 0 is given, missing anchors are not removed.
# keep-missing: 31622400 # 366 days
- # debug option that allows very small holddown times for key rollover
+ # debug option that allows very small holddown times for key rollover,
+ # otherwise the RFC mandates probe intervals must be at least 1 hour.
# permit-small-holddown: no
# the amount of memory to use for the key cache.
@@ -541,6 +580,8 @@ server:
# o typetransparent resolves normally for other types and other names
# o inform resolves normally, but logs client IP address
# o inform_deny drops queries and logs client IP address
+ # o always_transparent, always_refuse, always_nxdomain, resolve in
+ # that way but ignore local data for that name.
#
# defaults are localhost address, reverse for 127.0.0.1 and ::1
# and nxdomain for AS112 zones. If you configure one of these zones
@@ -567,6 +608,12 @@ server:
# you need to do the reverse notation yourself.
# local-data-ptr: "192.0.2.3 www.example.com"
+ # tag a localzone with a list of tag names (in "" with spaces between)
+ # local-zone-tag: "example.com" "tag2 tag3"
+
+ # add a netblock specific override to a localzone, with zone type
+ # local-zone-override: "example.com" 192.0.2.0/24 refuse
+
# service clients over SSL (on the TCP sockets), with plain DNS inside
# the SSL stream. Give the certificate to use and private key.
# default is "" (disabled). requires restart to take effect.
@@ -600,7 +647,7 @@ server:
# ratelimit-for-domain: example.com 1000
# override the ratelimits for all domains below a domain name
# can give this multiple times, the name closest to the zone is used.
- # ratelimit-below-domain: example 1000
+ # ratelimit-below-domain: com 1000
# Python config section. To enable:
# o use --with-pythonmodule to configure before compiling.
diff --git a/contrib/unbound/doc/example.conf.in b/contrib/unbound/doc/example.conf.in
index b5cc1c9..c520c88 100644
--- a/contrib/unbound/doc/example.conf.in
+++ b/contrib/unbound/doc/example.conf.in
@@ -1,7 +1,7 @@
#
# Example configuration file.
#
-# See unbound.conf(5) man page, version 1.5.8.
+# See unbound.conf(5) man page, version 1.5.10.
#
# this is a comment.
@@ -52,6 +52,15 @@ server:
# outgoing-interface: 192.0.2.153
# outgoing-interface: 2001:DB8::5
# outgoing-interface: 2001:DB8::6
+
+ # Specify a netblock to use remainder 64 bits as random bits for
+ # upstream queries. Uses freebind option (Linux).
+ # outgoing-interface: 2001:DB8::/64
+ # Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
+ # And: ip -6 route add local 2001:db8::/64 dev lo
+ # And set prefer-ip6: yes to use the ip6 randomness from a netblock.
+ # Set this to yes to prefer ipv6 upstream servers over ipv4.
+ # prefer-ip6: no
# number of ports to allocate per thread, determines the size of the
# port range that can be open simultaneously. About double the
@@ -93,6 +102,11 @@ server:
# (uses IP_BINDANY on FreeBSD).
# ip-transparent: no
+ # use IP_FREEBIND so the interface: addresses can be non-local
+ # and you can bind to nonexisting IPs and interfaces that are down.
+ # Linux only. On Linux you also have ip-transparent that is similar.
+ # ip-freebind: no
+
# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
# is set with msg-buffer-size). 1480 can solve fragmentation (timeouts).
# edns-buffer-size: 4096
@@ -157,6 +171,10 @@ server:
# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
# infra-cache-numhosts: 10000
+
+ # define a number of tags here, use with local-zone, access-control.
+ # repeat the define-tag statement to add additional tags.
+ # define-tag: "tag1 tag2 tag3"
# Enable IPv4, "yes" or "no".
# do-ip4: yes
@@ -198,6 +216,20 @@ server:
# access-control: ::1 allow
# access-control: ::ffff:127.0.0.1 allow
+ # tag access-control with list of tags (in "" with spaces between)
+ # Clients using this access control element use localzones that
+ # are tagged with one of these tags.
+ # access-control-tag: 192.0.2.0/24 "tag2 tag3"
+
+ # set action for particular tag for given access control element
+ # if you have multiple tag values, the tag used to lookup the action
+ # is the first tag match between access-control-tag and local-zone-tag
+ # where "first" comes from the order of the define-tag values.
+ # access-control-tag-action: 192.0.2.0/24 tag3 refuse
+
+ # set redirect data for particular tag for access control element
+ # access-control-tag-data: 192.0.2.0/24 tag2 "A 127.0.0.1"
+
# if given, a chroot(2) is done to the given directory.
# i.e. you can chroot to the working directory, for example,
# for extra security, but make sure all files are in that directory.
@@ -231,6 +263,8 @@ server:
# the working directory. The relative files in this config are
# relative to this directory. If you give "" the working directory
# is not changed.
+ # If you give a server: directory: dir before include: file statements
+ # then those includes can be relative to the working directory.
# directory: "@UNBOUND_RUN_DIR@"
# the log file, "" means log to stderr.
@@ -317,6 +351,7 @@ server:
# Domains (and domains in them) without support for dns-0x20 and
# the fallback fails because they keep sending different answers.
# caps-whitelist: "licdn.com"
+ # caps-whitelist: "senderbase.org"
# Enforce privacy of these addresses. Strips them away from answers.
# It may cause DNSSEC validation to additionally mark it as bogus.
@@ -364,6 +399,9 @@ server:
# into response messages when those sections are not required.
# minimal-responses: no
+ # true to disable DNSSEC lameness check in iterator.
+ # disable-dnssec-lame-check: no
+
# module configuration of the server. A string with identifiers
# separated by spaces. Syntax: "[dns64] [validator] iterator"
# module-config: "validator iterator"
@@ -459,7 +497,8 @@ server:
# If the value 0 is given, missing anchors are not removed.
# keep-missing: 31622400 # 366 days
- # debug option that allows very small holddown times for key rollover
+ # debug option that allows very small holddown times for key rollover,
+ # otherwise the RFC mandates probe intervals must be at least 1 hour.
# permit-small-holddown: no
# the amount of memory to use for the key cache.
@@ -541,6 +580,8 @@ server:
# o typetransparent resolves normally for other types and other names
# o inform resolves normally, but logs client IP address
# o inform_deny drops queries and logs client IP address
+ # o always_transparent, always_refuse, always_nxdomain, resolve in
+ # that way but ignore local data for that name.
#
# defaults are localhost address, reverse for 127.0.0.1 and ::1
# and nxdomain for AS112 zones. If you configure one of these zones
@@ -567,6 +608,12 @@ server:
# you need to do the reverse notation yourself.
# local-data-ptr: "192.0.2.3 www.example.com"
+ # tag a localzone with a list of tag names (in "" with spaces between)
+ # local-zone-tag: "example.com" "tag2 tag3"
+
+ # add a netblock specific override to a localzone, with zone type
+ # local-zone-override: "example.com" 192.0.2.0/24 refuse
+
# service clients over SSL (on the TCP sockets), with plain DNS inside
# the SSL stream. Give the certificate to use and private key.
# default is "" (disabled). requires restart to take effect.
@@ -600,7 +647,7 @@ server:
# ratelimit-for-domain: example.com 1000
# override the ratelimits for all domains below a domain name
# can give this multiple times, the name closest to the zone is used.
- # ratelimit-below-domain: example 1000
+ # ratelimit-below-domain: com 1000
# Python config section. To enable:
# o use --with-pythonmodule to configure before compiling.
diff --git a/contrib/unbound/doc/libunbound.3 b/contrib/unbound/doc/libunbound.3
index df4b8fd..1bf3fc2 100644
--- a/contrib/unbound/doc/libunbound.3
+++ b/contrib/unbound/doc/libunbound.3
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "libunbound" "3" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
@@ -43,7 +43,7 @@
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
-\- Unbound DNS validating resolver 1.5.8 functions.
+\- Unbound DNS validating resolver 1.5.10 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/contrib/unbound/doc/libunbound.3.in b/contrib/unbound/doc/libunbound.3.in
index df4b8fd..1bf3fc2 100644
--- a/contrib/unbound/doc/libunbound.3.in
+++ b/contrib/unbound/doc/libunbound.3.in
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "libunbound" "3" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
@@ -43,7 +43,7 @@
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
-\- Unbound DNS validating resolver 1.5.8 functions.
+\- Unbound DNS validating resolver 1.5.10 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/contrib/unbound/doc/unbound-anchor.8 b/contrib/unbound/doc/unbound-anchor.8
index c5d9d7f..fbc7e20 100644
--- a/contrib/unbound/doc/unbound-anchor.8
+++ b/contrib/unbound/doc/unbound-anchor.8
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-anchor" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
@@ -16,6 +16,8 @@
.SH "DESCRIPTION"
.B Unbound\-anchor
performs setup or update of the root trust anchor for DNSSEC validation.
+The program fetches the trust anchor with the method from RFC7958 when
+regular RFC5011 update fails to bring it up to date.
It can be run (as root) from the commandline, or run as part of startup
scripts. Before you start the \fIunbound\fR(8) DNS server.
.P
@@ -39,8 +41,8 @@ update certificate files.
.P
It tests if the root anchor file works, and if not, and an update is possible,
attempts to update the root anchor using the root update certificate.
-It performs a https fetch of root-anchors.xml and checks the results, if
-all checks are successful, it updates the root anchor file. Otherwise
+It performs a https fetch of root-anchors.xml and checks the results (RFC7958),
+if all checks are successful, it updates the root anchor file. Otherwise
the root anchor file is unchanged. It performs RFC5011 tracking if the
DNSSEC information available via the DNS makes that possible.
.P
diff --git a/contrib/unbound/doc/unbound-anchor.8.in b/contrib/unbound/doc/unbound-anchor.8.in
index de283e5..7403caa 100644
--- a/contrib/unbound/doc/unbound-anchor.8.in
+++ b/contrib/unbound/doc/unbound-anchor.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-anchor" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
@@ -16,6 +16,8 @@
.SH "DESCRIPTION"
.B Unbound\-anchor
performs setup or update of the root trust anchor for DNSSEC validation.
+The program fetches the trust anchor with the method from RFC7958 when
+regular RFC5011 update fails to bring it up to date.
It can be run (as root) from the commandline, or run as part of startup
scripts. Before you start the \fIunbound\fR(8) DNS server.
.P
@@ -39,8 +41,8 @@ update certificate files.
.P
It tests if the root anchor file works, and if not, and an update is possible,
attempts to update the root anchor using the root update certificate.
-It performs a https fetch of root-anchors.xml and checks the results, if
-all checks are successful, it updates the root anchor file. Otherwise
+It performs a https fetch of root-anchors.xml and checks the results (RFC7958),
+if all checks are successful, it updates the root anchor file. Otherwise
the root anchor file is unchanged. It performs RFC5011 tracking if the
DNSSEC information available via the DNS makes that possible.
.P
diff --git a/contrib/unbound/doc/unbound-checkconf.8 b/contrib/unbound/doc/unbound-checkconf.8
index f166720..3c8198b 100644
--- a/contrib/unbound/doc/unbound-checkconf.8
+++ b/contrib/unbound/doc/unbound-checkconf.8
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-checkconf" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/contrib/unbound/doc/unbound-checkconf.8.in b/contrib/unbound/doc/unbound-checkconf.8.in
index 92be13f..03f5b3c 100644
--- a/contrib/unbound/doc/unbound-checkconf.8.in
+++ b/contrib/unbound/doc/unbound-checkconf.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-checkconf" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/contrib/unbound/doc/unbound-control.8 b/contrib/unbound/doc/unbound-control.8
index 75219d2..892bbeb 100644
--- a/contrib/unbound/doc/unbound-control.8
+++ b/contrib/unbound/doc/unbound-control.8
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-control" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
diff --git a/contrib/unbound/doc/unbound-control.8.in b/contrib/unbound/doc/unbound-control.8.in
index 0e814b8..9089db9 100644
--- a/contrib/unbound/doc/unbound-control.8.in
+++ b/contrib/unbound/doc/unbound-control.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-control" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
diff --git a/contrib/unbound/doc/unbound-host.1 b/contrib/unbound/doc/unbound-host.1
index 28a50a8..ef1eaed 100644
--- a/contrib/unbound/doc/unbound-host.1
+++ b/contrib/unbound/doc/unbound-host.1
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound\-host" "1" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/contrib/unbound/doc/unbound-host.1.in b/contrib/unbound/doc/unbound-host.1.in
index 65253ad..04d19ad 100644
--- a/contrib/unbound/doc/unbound-host.1.in
+++ b/contrib/unbound/doc/unbound-host.1.in
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound\-host" "1" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/contrib/unbound/doc/unbound.8 b/contrib/unbound/doc/unbound.8
index d8c5494..26abc06 100644
--- a/contrib/unbound/doc/unbound.8
+++ b/contrib/unbound/doc/unbound.8
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound.8 -- unbound manual
.\"
@@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.5.8.
+\- Unbound DNS validating resolver 1.5.10.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/contrib/unbound/doc/unbound.8.in b/contrib/unbound/doc/unbound.8.in
index 4b752bb..78e497d 100644
--- a/contrib/unbound/doc/unbound.8.in
+++ b/contrib/unbound/doc/unbound.8.in
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound.8 -- unbound manual
.\"
@@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.5.8.
+\- Unbound DNS validating resolver 1.5.10.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/contrib/unbound/doc/unbound.conf.5 b/contrib/unbound/doc/unbound.conf.5
index 569bd26..6897761 100644
--- a/contrib/unbound/doc/unbound.conf.5
+++ b/contrib/unbound/doc/unbound.conf.5
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound.conf" "5" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -72,7 +72,8 @@ Processing continues as if the text from the included file was copied into
the config file at that point. If also using chroot, using full path names
for the included files works, relative pathnames for the included names work
if the directory where the daemon is started equals its chroot/working
-directory. Wildcards can be used to include multiple files, see \fIglob\fR(7).
+directory or is specified before the include statement with directory: dir.
+Wildcards can be used to include multiple files, see \fIglob\fR(7).
.SS "Server Options"
These options are part of the
.B server:
@@ -126,7 +127,7 @@ Detect source interface on UDP queries and copy them to replies. This
feature is experimental, and needs support in your OS for particular socket
options. Default value is no.
.TP
-.B outgoing\-interface: \fI<ip address>
+.B outgoing\-interface: \fI<ip address or ip6 netblock>
Interface to use to connect to the network. This interface is used to send
queries to authoritative servers and receive their replies. Can be given
multiple times to work on several interfaces. If none are given the
@@ -136,12 +137,28 @@ and
.B outgoing\-interface:
lines, the interfaces are then used for both purposes. Outgoing queries are
sent via a random outgoing interface to counter spoofing.
+.IP
+If an IPv6 netblock is specified instead of an individual IPv6 address,
+outgoing UDP queries will use a randomised source address taken from the
+netblock to counter spoofing. Requires the IPv6 netblock to be routed to the
+host running unbound, and requires OS support for unprivileged non-local binds
+(currently only supported on Linux). Several netblocks may be specified with
+multiple
+.B outgoing\-interface:
+options, but do not specify both an individual IPv6 address and an IPv6
+netblock, or the randomisation will be compromised. Consider combining with
+.B prefer\-ip6: yes
+to increase the likelihood of IPv6 nameservers being selected for queries.
+On Linux you need these two commands to be able to use the freebind socket
+option to receive traffic for the ip6 netblock:
+ip -6 addr add mynetblock/64 dev lo &&
+ip -6 route add local mynetblock/64 dev lo
.TP
.B outgoing\-range: \fI<number>
Number of ports to open. This number of file descriptors can be opened per
thread. Must be at least 1. Default depends on compile options. Larger
numbers need extra resources from the operating system. For performance a
-a very large value is best, use libevent to make this possible.
+very large value is best, use libevent to make this possible.
.TP
.B outgoing\-port\-permit: \fI<port number or range>
Permit unbound to open this port or range of ports for use to send queries.
@@ -277,6 +294,13 @@ and with this option you can select which (future) interfaces unbound
provides service on. This option needs unbound to be started with root
permissions on some systems. The option uses IP_BINDANY on FreeBSD systems.
.TP
+.B ip\-freebind: \fI<yes or no>
+If yes, then use IP_FREEBIND socket option on sockets where unbound
+is listening to incoming traffic. Default no. Allows you to bind to
+IP addresses that are nonlocal or do not exist, like when the network
+interface or IP address is down. Exists only on Linux, where the similar
+ip\-transparent option is also available.
+.TP
.B rrset\-cache\-size: \fI<number>
Number of bytes size of the RRset cache. Default is 4 megabytes.
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
@@ -322,6 +346,10 @@ Lower limit for dynamic retransmit timeout calculation in infrastructure
cache. Default is 50 milliseconds. Increase this value if using forwarders
needing more time to do recursive name resolution.
.TP
+.B define\-tag: \fI<"list of tags">
+Define the tags that can be used with local\-zone and access\-control.
+Enclose the list between quotes ("") and put spaces between tags.
+.TP
.B do\-ip4: \fI<yes or no>
Enable or disable whether ip4 queries are answered or issued. Default is yes.
.TP
@@ -332,6 +360,10 @@ IPv6 to the internet nameservers. With this option you can disable the
ipv6 transport for sending DNS traffic, it does not impact the contents of
the DNS traffic, which may have ip4 and ip6 addresses in it.
.TP
+.B prefer\-ip6: \fI<yes or no>
+If enabled, prefer IPv6 transport for sending DNS queries to internet
+nameservers. Default is no.
+.TP
.B do\-udp: \fI<yes or no>
Enable or disable whether UDP queries are answered or issued. Default is yes.
.TP
@@ -425,6 +457,23 @@ allowed full recursion but only the static data. With deny_non_local,
messages that are disallowed are dropped, with refuse_non_local they
receive error code REFUSED.
.TP
+.B access\-control\-tag: \fI<IP netblock> <"list of tags">
+Assign tags to access-control elements. Clients using this access control
+element use localzones that are tagged with one of these tags. Tags must be
+defined in \fIdefine\-tags\fR. Enclose list of tags in quotes ("") and put
+spaces between tags. If access\-control\-tag is configured for a netblock that
+does not have an access\-control, an access\-control element with action
+\fIallow\fR is configured for this netblock.
+.TP
+.B access\-control\-tag\-action: \fI<IP netblock> <tag> <action>
+Set action for particular tag for given access control element. If you have
+multiple tag values, the tag used to lookup the action is the first tag match
+between access\-control\-tag and local\-zone\-tag where "first" comes from the
+order of the define-tag values.
+.TP
+.B access\-control\-tag\-data: \fI<IP netblock> <tag> <"resource record string">
+Set redirect data for particular tag for given access control element.
+.TP
.B chroot: \fI<directory>
If chroot is enabled, you should pass the configfile (from the
commandline) as a full path from the original root. After the
@@ -462,6 +511,8 @@ requires privileges, then a reload will fail; a restart is needed.
Sets the working directory for the program. Default is "/var/unbound".
On Windows the string "%EXECUTABLE%" tries to change to the directory
that unbound.exe resides in.
+If you give a server: directory: dir before include: file statements
+then those includes can be relative to the working directory.
.TP
.B logfile: \fI<filename>
If "" is given, logging goes to stderr, or nowhere once daemonized.
@@ -570,6 +621,7 @@ might return nxdomain for empty nonterminals (that usually happen for reverse
IP address lookups), and thus may be incompatible with this. To try to avoid
this only DNSSEC-secure nxdomains are used, because the old software does not
have DNSSEC. Default is off.
+Currently, draft\-ietf\-dnsop\-nxdomain\-cut promotes this technique.
.TP
.B harden\-referral\-path: \fI<yes or no>
Harden the referral path by performing additional queries for
@@ -673,6 +725,13 @@ This may cause a slight speedup. The default is no, because the DNS
protocol RFCs mandate these sections, and the additional content could
be of use and save roundtrips for clients.
.TP
+.B disable-dnssec-lame-check: \fI<yes or no>
+If true, disables the DNSSEC lameness check in the iterator. This check
+sees if RRSIGs are present in the answer, when dnssec is expected,
+and retries another authority if RRSIGs are unexpectedly missing.
+The validator will insist in RRSIGs for DNSSEC signed domains regardless
+of this setting, if a trust anchor is loaded.
+.TP
.B module\-config: \fI<"module names">
Module configuration, a list of module names separated by spaces, surround
the string with quotes (""). The modules can be validator, iterator.
@@ -691,7 +750,9 @@ File with trust anchor for one zone, which is tracked with RFC5011 probes.
The probes are several times per month, thus the machine must be online
frequently. The initial file can be one with contents as described in
\fBtrust\-anchor\-file\fR. The file is written to when the anchor is updated,
-so the unbound user must have write permission.
+so the unbound user must have write permission. Write permission to the file,
+but also to the directory it is in (to create a temporary file, which is
+necessary to deal with filesystem full events).
.TP
.B trust\-anchor: \fI<"Resource Record">
A DS or DNSKEY RR for a key to use for validation. Multiple entries can be
@@ -866,6 +927,7 @@ address space are not validated. This is usually required whenever
Configure a local zone. The type determines the answer to give if
there is no match from local\-data. The types are deny, refuse, static,
transparent, redirect, nodefault, typetransparent, inform, inform_deny,
+always_transparent, always_refuse, always_nxdomain,
and are explained below. After that the default settings are listed. Use
local\-data: to enter data into the local zone. Answers for local zones
are authoritative DNS answers. By default the zones are class IN.
@@ -926,6 +988,15 @@ logged, eg. to run antivirus on them.
The query is dropped, like 'deny', and logged, like 'inform'. Ie. find
infected machines without answering the queries.
.TP 10
+\h'5'\fIalways_transparent\fR
+Like transparent, but ignores local data and resolves normally.
+.TP 10
+\h'5'\fIalways_refuse\fR
+Like refuse, but ignores local data and refuses the query.
+.TP 10
+\h'5'\fIalways_nxdomain\fR
+Like static, but ignores local data and returns nxdomain for the query.
+.TP 10
\h'5'\fInodefault\fR
Used to turn off default contents for AS112 zones. The other types
also turn off default contents for the zone. The 'nodefault' option
@@ -1043,6 +1114,18 @@ Configure local data shorthand for a PTR record with the reversed IPv4 or
IPv6 address and the host name. For example "192.0.2.4 www.example.com".
TTL can be inserted like this: "2001:DB8::4 7200 www.example.com"
.TP 5
+.B local\-zone\-tag: \fI<zone> <"list of tags">
+Assign tags to localzones. Tagged localzones will only be applied when the
+used access-control element has a matching tag. Tags must be defined in
+\fIdefine\-tags\fR. Enclose list of tags in quotes ("") and put spaces between
+tags.
+.TP 5
+.B local\-zone\-override: \fI<zone> <IP netblock> <type>
+Override the localzone type for queries from addresses matching netblock.
+Use this localzone type, regardless the type configured for the local-zone
+(both tagged and untagged) and regardless the type configured using
+access\-control\-tag\-action.
+.TP 5
.B ratelimit: \fI<number or 0>
Enable ratelimiting of queries sent to nameserver for performing recursion.
If 0, the default, it is disabled. This option is experimental at this time.
diff --git a/contrib/unbound/doc/unbound.conf.5.in b/contrib/unbound/doc/unbound.conf.5.in
index 3f84cac..f813c44 100644
--- a/contrib/unbound/doc/unbound.conf.5.in
+++ b/contrib/unbound/doc/unbound.conf.5.in
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound.conf" "5" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -72,7 +72,8 @@ Processing continues as if the text from the included file was copied into
the config file at that point. If also using chroot, using full path names
for the included files works, relative pathnames for the included names work
if the directory where the daemon is started equals its chroot/working
-directory. Wildcards can be used to include multiple files, see \fIglob\fR(7).
+directory or is specified before the include statement with directory: dir.
+Wildcards can be used to include multiple files, see \fIglob\fR(7).
.SS "Server Options"
These options are part of the
.B server:
@@ -126,7 +127,7 @@ Detect source interface on UDP queries and copy them to replies. This
feature is experimental, and needs support in your OS for particular socket
options. Default value is no.
.TP
-.B outgoing\-interface: \fI<ip address>
+.B outgoing\-interface: \fI<ip address or ip6 netblock>
Interface to use to connect to the network. This interface is used to send
queries to authoritative servers and receive their replies. Can be given
multiple times to work on several interfaces. If none are given the
@@ -136,12 +137,28 @@ and
.B outgoing\-interface:
lines, the interfaces are then used for both purposes. Outgoing queries are
sent via a random outgoing interface to counter spoofing.
+.IP
+If an IPv6 netblock is specified instead of an individual IPv6 address,
+outgoing UDP queries will use a randomised source address taken from the
+netblock to counter spoofing. Requires the IPv6 netblock to be routed to the
+host running unbound, and requires OS support for unprivileged non-local binds
+(currently only supported on Linux). Several netblocks may be specified with
+multiple
+.B outgoing\-interface:
+options, but do not specify both an individual IPv6 address and an IPv6
+netblock, or the randomisation will be compromised. Consider combining with
+.B prefer\-ip6: yes
+to increase the likelihood of IPv6 nameservers being selected for queries.
+On Linux you need these two commands to be able to use the freebind socket
+option to receive traffic for the ip6 netblock:
+ip -6 addr add mynetblock/64 dev lo &&
+ip -6 route add local mynetblock/64 dev lo
.TP
.B outgoing\-range: \fI<number>
Number of ports to open. This number of file descriptors can be opened per
thread. Must be at least 1. Default depends on compile options. Larger
numbers need extra resources from the operating system. For performance a
-a very large value is best, use libevent to make this possible.
+very large value is best, use libevent to make this possible.
.TP
.B outgoing\-port\-permit: \fI<port number or range>
Permit unbound to open this port or range of ports for use to send queries.
@@ -277,6 +294,13 @@ and with this option you can select which (future) interfaces unbound
provides service on. This option needs unbound to be started with root
permissions on some systems. The option uses IP_BINDANY on FreeBSD systems.
.TP
+.B ip\-freebind: \fI<yes or no>
+If yes, then use IP_FREEBIND socket option on sockets where unbound
+is listening to incoming traffic. Default no. Allows you to bind to
+IP addresses that are nonlocal or do not exist, like when the network
+interface or IP address is down. Exists only on Linux, where the similar
+ip\-transparent option is also available.
+.TP
.B rrset\-cache\-size: \fI<number>
Number of bytes size of the RRset cache. Default is 4 megabytes.
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
@@ -322,6 +346,10 @@ Lower limit for dynamic retransmit timeout calculation in infrastructure
cache. Default is 50 milliseconds. Increase this value if using forwarders
needing more time to do recursive name resolution.
.TP
+.B define\-tag: \fI<"list of tags">
+Define the tags that can be used with local\-zone and access\-control.
+Enclose the list between quotes ("") and put spaces between tags.
+.TP
.B do\-ip4: \fI<yes or no>
Enable or disable whether ip4 queries are answered or issued. Default is yes.
.TP
@@ -332,6 +360,10 @@ IPv6 to the internet nameservers. With this option you can disable the
ipv6 transport for sending DNS traffic, it does not impact the contents of
the DNS traffic, which may have ip4 and ip6 addresses in it.
.TP
+.B prefer\-ip6: \fI<yes or no>
+If enabled, prefer IPv6 transport for sending DNS queries to internet
+nameservers. Default is no.
+.TP
.B do\-udp: \fI<yes or no>
Enable or disable whether UDP queries are answered or issued. Default is yes.
.TP
@@ -425,6 +457,23 @@ allowed full recursion but only the static data. With deny_non_local,
messages that are disallowed are dropped, with refuse_non_local they
receive error code REFUSED.
.TP
+.B access\-control\-tag: \fI<IP netblock> <"list of tags">
+Assign tags to access-control elements. Clients using this access control
+element use localzones that are tagged with one of these tags. Tags must be
+defined in \fIdefine\-tags\fR. Enclose list of tags in quotes ("") and put
+spaces between tags. If access\-control\-tag is configured for a netblock that
+does not have an access\-control, an access\-control element with action
+\fIallow\fR is configured for this netblock.
+.TP
+.B access\-control\-tag\-action: \fI<IP netblock> <tag> <action>
+Set action for particular tag for given access control element. If you have
+multiple tag values, the tag used to lookup the action is the first tag match
+between access\-control\-tag and local\-zone\-tag where "first" comes from the
+order of the define-tag values.
+.TP
+.B access\-control\-tag\-data: \fI<IP netblock> <tag> <"resource record string">
+Set redirect data for particular tag for given access control element.
+.TP
.B chroot: \fI<directory>
If chroot is enabled, you should pass the configfile (from the
commandline) as a full path from the original root. After the
@@ -462,6 +511,8 @@ requires privileges, then a reload will fail; a restart is needed.
Sets the working directory for the program. Default is "@UNBOUND_RUN_DIR@".
On Windows the string "%EXECUTABLE%" tries to change to the directory
that unbound.exe resides in.
+If you give a server: directory: dir before include: file statements
+then those includes can be relative to the working directory.
.TP
.B logfile: \fI<filename>
If "" is given, logging goes to stderr, or nowhere once daemonized.
@@ -570,6 +621,7 @@ might return nxdomain for empty nonterminals (that usually happen for reverse
IP address lookups), and thus may be incompatible with this. To try to avoid
this only DNSSEC-secure nxdomains are used, because the old software does not
have DNSSEC. Default is off.
+Currently, draft\-ietf\-dnsop\-nxdomain\-cut promotes this technique.
.TP
.B harden\-referral\-path: \fI<yes or no>
Harden the referral path by performing additional queries for
@@ -673,6 +725,13 @@ This may cause a slight speedup. The default is no, because the DNS
protocol RFCs mandate these sections, and the additional content could
be of use and save roundtrips for clients.
.TP
+.B disable-dnssec-lame-check: \fI<yes or no>
+If true, disables the DNSSEC lameness check in the iterator. This check
+sees if RRSIGs are present in the answer, when dnssec is expected,
+and retries another authority if RRSIGs are unexpectedly missing.
+The validator will insist in RRSIGs for DNSSEC signed domains regardless
+of this setting, if a trust anchor is loaded.
+.TP
.B module\-config: \fI<"module names">
Module configuration, a list of module names separated by spaces, surround
the string with quotes (""). The modules can be validator, iterator.
@@ -691,7 +750,9 @@ File with trust anchor for one zone, which is tracked with RFC5011 probes.
The probes are several times per month, thus the machine must be online
frequently. The initial file can be one with contents as described in
\fBtrust\-anchor\-file\fR. The file is written to when the anchor is updated,
-so the unbound user must have write permission.
+so the unbound user must have write permission. Write permission to the file,
+but also to the directory it is in (to create a temporary file, which is
+necessary to deal with filesystem full events).
.TP
.B trust\-anchor: \fI<"Resource Record">
A DS or DNSKEY RR for a key to use for validation. Multiple entries can be
@@ -866,6 +927,7 @@ address space are not validated. This is usually required whenever
Configure a local zone. The type determines the answer to give if
there is no match from local\-data. The types are deny, refuse, static,
transparent, redirect, nodefault, typetransparent, inform, inform_deny,
+always_transparent, always_refuse, always_nxdomain,
and are explained below. After that the default settings are listed. Use
local\-data: to enter data into the local zone. Answers for local zones
are authoritative DNS answers. By default the zones are class IN.
@@ -926,6 +988,15 @@ logged, eg. to run antivirus on them.
The query is dropped, like 'deny', and logged, like 'inform'. Ie. find
infected machines without answering the queries.
.TP 10
+\h'5'\fIalways_transparent\fR
+Like transparent, but ignores local data and resolves normally.
+.TP 10
+\h'5'\fIalways_refuse\fR
+Like refuse, but ignores local data and refuses the query.
+.TP 10
+\h'5'\fIalways_nxdomain\fR
+Like static, but ignores local data and returns nxdomain for the query.
+.TP 10
\h'5'\fInodefault\fR
Used to turn off default contents for AS112 zones. The other types
also turn off default contents for the zone. The 'nodefault' option
@@ -1043,6 +1114,18 @@ Configure local data shorthand for a PTR record with the reversed IPv4 or
IPv6 address and the host name. For example "192.0.2.4 www.example.com".
TTL can be inserted like this: "2001:DB8::4 7200 www.example.com"
.TP 5
+.B local\-zone\-tag: \fI<zone> <"list of tags">
+Assign tags to localzones. Tagged localzones will only be applied when the
+used access-control element has a matching tag. Tags must be defined in
+\fIdefine\-tags\fR. Enclose list of tags in quotes ("") and put spaces between
+tags.
+.TP 5
+.B local\-zone\-override: \fI<zone> <IP netblock> <type>
+Override the localzone type for queries from addresses matching netblock.
+Use this localzone type, regardless the type configured for the local-zone
+(both tagged and untagged) and regardless the type configured using
+access\-control\-tag\-action.
+.TP 5
.B ratelimit: \fI<number or 0>
Enable ratelimiting of queries sent to nameserver for performing recursion.
If 0, the default, it is disabled. This option is experimental at this time.
diff --git a/contrib/unbound/doc/unbound.doxygen b/contrib/unbound/doc/unbound.doxygen
index 43f2e38..fe39876 100644
--- a/contrib/unbound/doc/unbound.doxygen
+++ b/contrib/unbound/doc/unbound.doxygen
@@ -623,7 +623,9 @@ EXCLUDE = ./build \
pythonmod/examples/resip.py \
libunbound/python/unbound.py \
libunbound/python/libunbound_wrap.c \
- ./ldns-src
+ ./ldns-src \
+ doc/control_proto_spec.txt \
+ doc/requirements.txt
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
diff --git a/contrib/unbound/iterator/iter_fwd.c b/contrib/unbound/iterator/iter_fwd.c
index 0feee03..3e580ca 100644
--- a/contrib/unbound/iterator/iter_fwd.c
+++ b/contrib/unbound/iterator/iter_fwd.c
@@ -294,6 +294,7 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
uint8_t* dname;
size_t dname_len;
for(s = cfg->stubs; s; s = s->next) {
+ if(!s->name) continue;
dname = sldns_str2wire_dname(s->name, &dname_len);
if(!dname) {
log_err("cannot parse stub name '%s'", s->name);
diff --git a/contrib/unbound/iterator/iter_hints.c b/contrib/unbound/iterator/iter_hints.c
index 217dfa2..5fd9017 100644
--- a/contrib/unbound/iterator/iter_hints.c
+++ b/contrib/unbound/iterator/iter_hints.c
@@ -147,6 +147,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:84::b")) goto failed;
if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed;
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
+ if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed;
if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) goto failed;
if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::53")) goto failed;
if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) goto failed;
diff --git a/contrib/unbound/iterator/iter_utils.c b/contrib/unbound/iterator/iter_utils.c
index 58e62fb..874dd68 100644
--- a/contrib/unbound/iterator/iter_utils.c
+++ b/contrib/unbound/iterator/iter_utils.c
@@ -360,6 +360,39 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
}
}
*selected_rtt = low_rtt;
+
+ if (env->cfg->prefer_ip6) {
+ int got_num6 = 0;
+ int low_rtt6 = 0;
+ int i;
+ prev = NULL;
+ a = dp->result_list;
+ for(i = 0; i < got_num; i++) {
+ swap_to_front = 0;
+ if(a->addr.ss_family == AF_INET6) {
+ got_num6++;
+ swap_to_front = 1;
+ if(low_rtt6 == 0 || a->sel_rtt < low_rtt6) {
+ low_rtt6 = a->sel_rtt;
+ }
+ }
+ /* swap to front if IPv6, or move to next result */
+ if(swap_to_front && prev) {
+ n = a->next_result;
+ prev->next_result = n;
+ a->next_result = dp->result_list;
+ dp->result_list = a;
+ a = n;
+ } else {
+ prev = a;
+ a = a->next_result;
+ }
+ }
+ if(got_num6 > 0) {
+ got_num = got_num6;
+ *selected_rtt = low_rtt6;
+ }
+ }
return got_num;
}
@@ -590,6 +623,27 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
return 1;
}
+int
+iter_indicates_dnssec_fwd(struct module_env* env, struct query_info *qinfo)
+{
+ struct trust_anchor* a;
+ if(!env || !env->anchors || !qinfo || !qinfo->qname)
+ return 0;
+ /* a trust anchor exists above the name? */
+ if((a=anchors_lookup(env->anchors, qinfo->qname, qinfo->qname_len,
+ qinfo->qclass))) {
+ if(a->numDS == 0 && a->numDNSKEY == 0) {
+ /* insecure trust point */
+ lock_basic_unlock(&a->lock);
+ return 0;
+ }
+ lock_basic_unlock(&a->lock);
+ return 1;
+ }
+ /* no trust anchor above it. */
+ return 0;
+}
+
int
iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
struct dns_msg* msg, uint16_t dclass)
diff --git a/contrib/unbound/iterator/iter_utils.h b/contrib/unbound/iterator/iter_utils.h
index 3a4df3e..50c5fc0 100644
--- a/contrib/unbound/iterator/iter_utils.h
+++ b/contrib/unbound/iterator/iter_utils.h
@@ -174,6 +174,18 @@ int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp);
/**
+ * See if qname has DNSSEC needs in the forwarding case. This is true if
+ * there is a trust anchor above it. Whether there is an insecure delegation
+ * to the data is unknown, but CD-retry is needed.
+ * @param env: environment with anchors.
+ * @param qinfo: query name and class.
+ * @return true if trust anchor above qname, false if no anchor or insecure
+ * point above qname.
+ */
+int iter_indicates_dnssec_fwd(struct module_env* env,
+ struct query_info *qinfo);
+
+/**
* See if delegation is expected to have DNSSEC information (RRSIGs) in
* its answers, or not. Inspects delegation point (name), trust anchors,
* and delegation message (DS RRset) to determine this.
diff --git a/contrib/unbound/iterator/iterator.c b/contrib/unbound/iterator/iterator.c
index b1bf902..cc7e937 100644
--- a/contrib/unbound/iterator/iterator.c
+++ b/contrib/unbound/iterator/iterator.c
@@ -82,20 +82,6 @@ iter_init(struct module_env* env, int id)
log_err("iterator: could not apply configuration settings.");
return 0;
}
- if(env->cfg->qname_minimisation) {
- uint8_t dname[LDNS_MAX_DOMAINLEN+1];
- size_t len = sizeof(dname);
- if(sldns_str2wire_dname_buf("ip6.arpa.", dname, &len) != 0) {
- log_err("ip6.arpa. parse error");
- return 0;
- }
- iter_env->ip6arpa_dname = (uint8_t*)malloc(len);
- if(!iter_env->ip6arpa_dname) {
- log_err("malloc failure");
- return 0;
- }
- memcpy(iter_env->ip6arpa_dname, dname, len);
- }
return 1;
}
@@ -117,7 +103,6 @@ iter_deinit(struct module_env* env, int id)
if(!env || !env->modinfo[id])
return;
iter_env = (struct iter_env*)env->modinfo[id];
- free(iter_env->ip6arpa_dname);
free(iter_env->target_fetch_policy);
priv_delete(iter_env->priv);
donotq_delete(iter_env->donotq);
@@ -162,6 +147,8 @@ iter_new(struct module_qstate* qstate, int id)
/* Start with the (current) qname. */
iq->qchase = qstate->qinfo;
outbound_list_init(&iq->outlist);
+ iq->minimise_count = 0;
+ iq->minimise_timeout_count = 0;
if (qstate->env->cfg->qname_minimisation)
iq->minimisation_state = INIT_MINIMISE_STATE;
else
@@ -229,6 +216,7 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) {
/* mark address as failed. */
struct delegpt_ns* dpns = NULL;
+ super_iq->num_target_queries--;
if(super_iq->dp)
dpns = delegpt_find_ns(super_iq->dp,
qstate->qinfo.qname, qstate->qinfo.qname_len);
@@ -248,7 +236,6 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
log_err("out of memory adding missing");
}
dpns->resolved = 1; /* mark as failed */
- super_iq->num_target_queries--;
}
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS) {
/* prime failed to get delegation */
@@ -1800,6 +1787,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
int tf_policy;
struct delegpt_addr* target;
struct outbound_entry* outq;
+ /* EDNS options to set on outgoing packet */
+ struct edns_option* opt_list = NULL;
/* NOTE: a request will encounter this state for each target it
* needs to send a query to. That is, at least one per referral,
@@ -2009,9 +1998,10 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(iq->minimisation_state == INIT_MINIMISE_STATE) {
- /* (Re)set qinfo_out to (new) delegation point, except
- * when qinfo_out is already a subdomain of dp. This happens
- * when resolving ip6.arpa dnames. */
+ /* (Re)set qinfo_out to (new) delegation point, except when
+ * qinfo_out is already a subdomain of dp. This happens when
+ * increasing by more than one label at once (QNAMEs with more
+ * than MAX_MINIMISE_COUNT labels). */
if(!(iq->qinfo_out.qname_len
&& dname_subdomain_c(iq->qchase.qname,
iq->qinfo_out.qname)
@@ -2019,30 +2009,52 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->dp->name))) {
iq->qinfo_out.qname = iq->dp->name;
iq->qinfo_out.qname_len = iq->dp->namelen;
- iq->qinfo_out.qtype = LDNS_RR_TYPE_NS;
+ iq->qinfo_out.qtype = LDNS_RR_TYPE_A;
iq->qinfo_out.qclass = iq->qchase.qclass;
+ iq->minimise_count = 0;
}
iq->minimisation_state = MINIMISE_STATE;
}
if(iq->minimisation_state == MINIMISE_STATE) {
- int labdiff = dname_count_labels(iq->qchase.qname) -
+ int qchaselabs = dname_count_labels(iq->qchase.qname);
+ int labdiff = qchaselabs -
dname_count_labels(iq->qinfo_out.qname);
iq->qinfo_out.qname = iq->qchase.qname;
iq->qinfo_out.qname_len = iq->qchase.qname_len;
+ iq->minimise_count++;
+ iq->minimise_timeout_count = 0;
- /* Special treatment for ip6.arpa lookups.
- * Reverse IPv6 dname has 34 labels, increment the IP part
- * (usually first 32 labels) by 8 labels (7 more than the
- * default 1 label increment). */
- if(labdiff <= 32 &&
- dname_subdomain_c(iq->qchase.qname, ie->ip6arpa_dname)) {
- labdiff -= 7;
- /* Small chance of zone cut after first label. Stop
- * minimising */
- if(labdiff <= 1)
- labdiff = 0;
+ iter_dec_attempts(iq->dp, 1);
+
+ /* Limit number of iterations for QNAMEs with more
+ * than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB
+ * labels of QNAME always individually.
+ */
+ if(qchaselabs > MAX_MINIMISE_COUNT && labdiff > 1 &&
+ iq->minimise_count > MINIMISE_ONE_LAB) {
+ if(iq->minimise_count < MAX_MINIMISE_COUNT) {
+ int multilabs = qchaselabs - 1 -
+ MINIMISE_ONE_LAB;
+ int extralabs = multilabs /
+ MINIMISE_MULTIPLE_LABS;
+
+ if (MAX_MINIMISE_COUNT - iq->minimise_count >=
+ multilabs % MINIMISE_MULTIPLE_LABS)
+ /* Default behaviour is to add 1 label
+ * every iteration. Therefore, decrement
+ * the extralabs by 1 */
+ extralabs--;
+ if (extralabs < labdiff)
+ labdiff -= extralabs;
+ else
+ labdiff = 1;
+ }
+ /* Last minimised iteration, send all labels with
+ * QTYPE=NS */
+ else
+ labdiff = 1;
}
if(labdiff > 1) {
@@ -2051,8 +2063,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
&iq->qinfo_out.qname_len,
labdiff-1);
}
- if(labdiff < 1 ||
- (labdiff < 2 && iq->qchase.qtype == LDNS_RR_TYPE_DS))
+ if(labdiff < 1 || (labdiff < 2
+ && (iq->qchase.qtype == LDNS_RR_TYPE_DS
+ || iq->qchase.qtype == LDNS_RR_TYPE_A)))
/* Stop minimising this query, resolve "as usual" */
iq->minimisation_state = DONOT_MINIMISE_STATE;
else {
@@ -2068,12 +2081,18 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
* cached as NOERROR/NODATA */
return 1;
}
-
}
- if(iq->minimisation_state == SKIP_MINIMISE_STATE)
- /* Do not increment qname, continue incrementing next
- * iteration */
- iq->minimisation_state = MINIMISE_STATE;
+ if(iq->minimisation_state == SKIP_MINIMISE_STATE) {
+ iq->minimise_timeout_count++;
+ if(iq->minimise_timeout_count < MAX_MINIMISE_TIMEOUT_COUNT)
+ /* Do not increment qname, continue incrementing next
+ * iteration */
+ iq->minimisation_state = MINIMISE_STATE;
+ else
+ /* Too many time-outs detected for this QNAME and QTYPE.
+ * We give up, disable QNAME minimisation. */
+ iq->minimisation_state = DONOT_MINIMISE_STATE;
+ }
if(iq->minimisation_state == DONOT_MINIMISE_STATE)
iq->qinfo_out = iq->qchase;
@@ -2090,10 +2109,16 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
outq = (*qstate->env->send_query)(
iq->qinfo_out.qname, iq->qinfo_out.qname_len,
iq->qinfo_out.qtype, iq->qinfo_out.qclass,
- iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD,
+ iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
+ /* unset CD if to forwarder(RD set) and not dnssec retry
+ * (blacklist nonempty) and no trust-anchors are configured
+ * above the qname or on the first attempt when dnssec is on */
+ EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
+ !qstate->blacklist&&(!iter_indicates_dnssec_fwd(qstate->env,
+ &iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
- ie, iq), &target->addr, target->addrlen, iq->dp->name,
- iq->dp->namelen, qstate);
+ ie, iq), opt_list, &target->addr, target->addrlen,
+ iq->dp->name, iq->dp->namelen, qstate);
if(!outq) {
log_addr(VERB_DETAIL, "error sending query to auth server",
&target->addr, target->addrlen);
@@ -2145,7 +2170,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iq->num_current_queries--;
if(iq->response == NULL) {
/* Don't increment qname when QNAME minimisation is enabled */
- if (qstate->env->cfg->qname_minimisation)
+ if(qstate->env->cfg->qname_minimisation)
iq->minimisation_state = SKIP_MINIMISE_STATE;
iq->chase_to_rd = 0;
iq->dnssec_lame_query = 0;
@@ -2161,8 +2186,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* differently. No queries should be sent elsewhere */
type = RESPONSE_TYPE_ANSWER;
}
- if(iq->dnssec_expected && !iq->dnssec_lame_query &&
+ if(!qstate->env->cfg->disable_dnssec_lame_check && iq->dnssec_expected
+ && !iq->dnssec_lame_query &&
!(iq->chase_flags&BIT_RD)
+ && iq->sent_count < DNSSEC_LAME_DETECT_COUNT
&& type != RESPONSE_TYPE_LAME
&& type != RESPONSE_TYPE_REC_LAME
&& type != RESPONSE_TYPE_THROWAWAY
@@ -2250,10 +2277,39 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
if(iq->minimisation_state != DONOT_MINIMISE_STATE) {
/* Best effort qname-minimisation.
* Stop minimising and send full query when RCODE
- * is not NOERROR */
+ * is not NOERROR. */
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
LDNS_RCODE_NOERROR)
iq->minimisation_state = DONOT_MINIMISE_STATE;
+ if(FLAGS_GET_RCODE(iq->response->rep->flags) ==
+ LDNS_RCODE_NXDOMAIN) {
+ /* Stop resolving when NXDOMAIN is DNSSEC
+ * signed. Based on assumption that namservers
+ * serving signed zones do not return NXDOMAIN
+ * for empty-non-terminals. */
+ if(iq->dnssec_expected)
+ return final_state(iq);
+ /* Make subrequest to validate intermediate
+ * NXDOMAIN if harden-below-nxdomain is
+ * enabled. */
+ if(qstate->env->cfg->harden_below_nxdomain) {
+ struct module_qstate* subq = NULL;
+ log_query_info(VERB_QUERY,
+ "schedule NXDOMAIN validation:",
+ &iq->response->qinfo);
+ if(!generate_sub_request(
+ iq->response->qinfo.qname,
+ iq->response->qinfo.qname_len,
+ iq->response->qinfo.qtype,
+ iq->response->qinfo.qclass,
+ qstate, id, iq,
+ INIT_REQUEST_STATE,
+ FINISHED_STATE, &subq, 1))
+ verbose(VERB_ALGO,
+ "could not validate NXDOMAIN "
+ "response");
+ }
+ }
return next_state(iq, QUERYTARGETS_STATE);
}
return final_state(iq);
@@ -2605,6 +2661,10 @@ processTargetResponse(struct module_qstate* qstate, int id,
log_query_info(VERB_ALGO, "processTargetResponse", &qstate->qinfo);
log_query_info(VERB_ALGO, "processTargetResponse super", &forq->qinfo);
+ /* Tell the originating event that this target query has finished
+ * (regardless if it succeeded or not). */
+ foriq->num_target_queries--;
+
/* check to see if parent event is still interested (in orig name). */
if(!foriq->dp) {
verbose(VERB_ALGO, "subq: parent not interested, was reset");
@@ -2620,10 +2680,6 @@ processTargetResponse(struct module_qstate* qstate, int id,
return;
}
- /* Tell the originating event that this target query has finished
- * (regardless if it succeeded or not). */
- foriq->num_target_queries--;
-
/* if iq->query_for_pside_glue then add the pside_glue (marked lame) */
if(iq->pside_glue) {
/* if the pside_glue is NULL, then it could not be found,
@@ -3082,7 +3138,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
goto handle_it;
}
/* edns is not examined, but removed from message to help cache */
- if(parse_extract_edns(prs, &edns) != LDNS_RCODE_NOERROR)
+ if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
+ LDNS_RCODE_NOERROR)
goto handle_it;
/* remove CD-bit, we asked for in case we handle validation ourself */
prs->flags &= ~BIT_CD;
diff --git a/contrib/unbound/iterator/iterator.h b/contrib/unbound/iterator/iterator.h
index b7aa82e..5585f57 100644
--- a/contrib/unbound/iterator/iterator.h
+++ b/contrib/unbound/iterator/iterator.h
@@ -61,6 +61,23 @@ struct rbtree_t;
#define MAX_REFERRAL_COUNT 130
/** max number of queries-sent-out. Make sure large NS set does not loop */
#define MAX_SENT_COUNT 32
+/** max number of queries for which to perform dnsseclameness detection,
+ * (rrsigs misssing detection) after that, just pick up that response */
+#define DNSSEC_LAME_DETECT_COUNT 4
+/**
+ * max number of QNAME minimisation iterations. Limits number of queries for
+ * QNAMEs with a lot of labels.
+*/
+#define MAX_MINIMISE_COUNT 10
+/* max number of time-outs for minimised query. Prevents resolving failures
+ * when the QNAME minimisation QTYPE is blocked. */
+#define MAX_MINIMISE_TIMEOUT_COUNT 3
+/**
+ * number of labels from QNAME that are always send individually when using
+ * QNAME minimisation, even when the number of labels of the QNAME is bigger
+ * tham MAX_MINIMISE_COUNT */
+#define MINIMISE_ONE_LAB 4
+#define MINIMISE_MULTIPLE_LABS (MAX_MINIMISE_COUNT - MINIMISE_ONE_LAB)
/** at what query-sent-count to stop target fetch policy */
#define TARGET_FETCH_STOP 3
/** how nice is a server without further information, in msec
@@ -349,7 +366,7 @@ struct iter_qstate {
/** list of pending queries to authoritative servers. */
struct outbound_list outlist;
- /** QNAME minimisation state */
+ /** QNAME minimisation state, RFC7816 */
enum minimisation_state minimisation_state;
/**
@@ -357,6 +374,17 @@ struct iter_qstate {
* when qname minimisation is enabled.
*/
struct query_info qinfo_out;
+
+ /**
+ * Count number of QNAME minisation iterations. Used to limit number of
+ * outgoing queries when QNAME minimisation is enabled.
+ */
+ int minimise_count;
+
+ /**
+ * Count number of time-outs. Used to prevent resolving failures when
+ * the QNAME minimisation QTYPE is blocked. */
+ int minimise_timeout_count;
};
/**
diff --git a/contrib/unbound/libunbound/context.h b/contrib/unbound/libunbound/context.h
index 31ca09c..d32c0b0 100644
--- a/contrib/unbound/libunbound/context.h
+++ b/contrib/unbound/libunbound/context.h
@@ -49,7 +49,7 @@
struct libworker;
struct tube;
struct sldns_buffer;
-struct event_base;
+struct ub_event_base;
/**
* The context structure
@@ -114,7 +114,7 @@ struct ub_ctx {
struct ub_randstate* seed_rnd;
/** event base for event oriented interface */
- struct event_base* event_base;
+ struct ub_event_base* event_base;
/** libworker for event based interface */
struct libworker* event_worker;
diff --git a/contrib/unbound/libunbound/libunbound.c b/contrib/unbound/libunbound/libunbound.c
index 992509e..69ccb08 100644
--- a/contrib/unbound/libunbound/libunbound.c
+++ b/contrib/unbound/libunbound/libunbound.c
@@ -57,6 +57,7 @@
#include "util/random.h"
#include "util/net_help.h"
#include "util/tube.h"
+#include "util/ub_event.h"
#include "services/modstack.h"
#include "services/localzone.h"
#include "services/cache/infra.h"
@@ -170,6 +171,20 @@ ub_ctx_create(void)
}
struct ub_ctx*
+ub_ctx_create_ub_event(struct ub_event_base* ueb)
+{
+ struct ub_ctx* ctx = ub_ctx_create_nopipe();
+ if(!ctx)
+ return NULL;
+ /* no pipes, but we have the locks to make sure everything works */
+ ctx->created_bg = 0;
+ ctx->dothread = 1; /* the processing is in the same process,
+ makes ub_cancel and ub_ctx_delete do the right thing */
+ ctx->event_base = ueb;
+ return ctx;
+}
+
+struct ub_ctx*
ub_ctx_create_event(struct event_base* eb)
{
struct ub_ctx* ctx = ub_ctx_create_nopipe();
@@ -179,7 +194,11 @@ ub_ctx_create_event(struct event_base* eb)
ctx->created_bg = 0;
ctx->dothread = 1; /* the processing is in the same process,
makes ub_cancel and ub_ctx_delete do the right thing */
- ctx->event_base = eb;
+ ctx->event_base = ub_libevent_event_base(eb);
+ if (!ctx->event_base) {
+ ub_ctx_delete(ctx);
+ return NULL;
+ }
return ctx;
}
@@ -698,6 +717,9 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
}
}
+ /* set time in case answer comes from cache */
+ ub_comm_base_now(ctx->event_worker->base);
+
/* create new ctx_query and attempt to add to the list */
q = context_new(ctx, name, rrtype, rrclass, (ub_callback_t)callback,
mydata);
@@ -1323,10 +1345,12 @@ const char* ub_version(void)
int
ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) {
+ struct ub_event_base* new_base;
+
if (!ctx || !ctx->event_base || !base) {
return UB_INITFAIL;
}
- if (ctx->event_base == base) {
+ if (ub_libevent_get_event_base(ctx->event_base) == base) {
/* already set */
return UB_NOERROR;
}
@@ -1335,9 +1359,11 @@ ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) {
/* destroy the current worker - safe to pass in NULL */
libworker_delete_event(ctx->event_worker);
ctx->event_worker = NULL;
- ctx->event_base = base;
+ new_base = ub_libevent_event_base(base);
+ if (new_base)
+ ctx->event_base = new_base;
ctx->created_bg = 0;
ctx->dothread = 1;
lock_basic_unlock(&ctx->cfglock);
- return UB_NOERROR;
+ return new_base ? UB_NOERROR : UB_INITFAIL;
}
diff --git a/contrib/unbound/libunbound/libworker.c b/contrib/unbound/libunbound/libworker.c
index ad1f84c..6f53541 100644
--- a/contrib/unbound/libunbound/libworker.c
+++ b/contrib/unbound/libunbound/libworker.c
@@ -119,7 +119,7 @@ libworker_delete_event(struct libworker* w)
/** setup fresh libworker struct */
static struct libworker*
-libworker_setup(struct ub_ctx* ctx, int is_bg, struct event_base* eb)
+libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
{
unsigned int seed;
struct libworker* w = (struct libworker*)calloc(1, sizeof(*w));
@@ -258,7 +258,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct event_base* eb)
}
struct libworker* libworker_create_event(struct ub_ctx* ctx,
- struct event_base* eb)
+ struct ub_event_base* eb)
{
return libworker_setup(ctx, 0, eb);
}
@@ -581,6 +581,7 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
edns->ext_rcode = 0;
edns->edns_version = 0;
edns->bits = EDNS_DO;
+ edns->opt_list = NULL;
if(sldns_buffer_capacity(w->back->udp_buff) < 65535)
edns->udp_size = (uint16_t)sldns_buffer_capacity(
w->back->udp_buff);
@@ -607,7 +608,8 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
if(local_zones_answer(ctx->local_zones, &qinfo, &edns,
- w->back->udp_buff, w->env->scratch, NULL)) {
+ w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0)) {
regional_free_all(w->env->scratch);
libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
w->back->udp_buff, sec_status_insecure, NULL);
@@ -677,7 +679,8 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
if(local_zones_answer(ctx->local_zones, &qinfo, &edns,
- w->back->udp_buff, w->env->scratch, NULL)) {
+ w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0)) {
regional_free_all(w->env->scratch);
free(qinfo.qname);
libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
@@ -797,7 +800,8 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
if(local_zones_answer(w->ctx->local_zones, &qinfo, &edns,
- w->back->udp_buff, w->env->scratch, NULL)) {
+ w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0)) {
regional_free_all(w->env->scratch);
q->msg_security = sec_status_insecure;
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL);
@@ -822,9 +826,9 @@ void libworker_alloc_cleanup(void* arg)
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
- int want_dnssec, int nocaps, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* zone, size_t zonelen,
- struct module_qstate* q)
+ int want_dnssec, int nocaps, struct edns_option* opt_list,
+ struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
+ size_t zonelen, struct module_qstate* q)
{
struct libworker* w = (struct libworker*)q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@@ -834,9 +838,9 @@ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
e->qstate = q;
e->qsent = outnet_serviced_query(w->back, qname,
qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps,
- q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
- addrlen, zone, zonelen, libworker_handle_service_reply, e,
- w->back->udp_buff);
+ q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, opt_list,
+ addr, addrlen, zone, zonelen, libworker_handle_service_reply,
+ e, w->back->udp_buff);
if(!e->qsent) {
return NULL;
}
@@ -955,7 +959,8 @@ struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
+ struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{
diff --git a/contrib/unbound/libunbound/libworker.h b/contrib/unbound/libunbound/libworker.h
index 0103b5d..0014347 100644
--- a/contrib/unbound/libunbound/libworker.h
+++ b/contrib/unbound/libunbound/libworker.h
@@ -58,7 +58,7 @@ struct comm_reply;
struct regional;
struct tube;
struct sldns_buffer;
-struct event_base;
+struct ub_event_base;
/**
* The library-worker status structure
@@ -115,7 +115,7 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q);
* @return new worker or NULL.
*/
struct libworker* libworker_create_event(struct ub_ctx* ctx,
- struct event_base* eb);
+ struct ub_event_base* eb);
/**
* Attach context_query to mesh for callback in event-driven setup.
diff --git a/contrib/unbound/libunbound/python/libunbound.i b/contrib/unbound/libunbound/python/libunbound.i
index 50a9b67..84a5369 100644
--- a/contrib/unbound/libunbound/python/libunbound.i
+++ b/contrib/unbound/libunbound/python/libunbound.i
@@ -945,7 +945,7 @@ int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, v
:param idnname: (unicode string) IDN name
:returns: (string) domain name
"""
- return '.'.join([encodings.idna.ToASCII(a) for a in idnname.split('.')])
+ return '.'.join([encodings.idna.ToASCII(a) if a else '' for a in idnname.split('.')])
def dname2idn(name):
"""Converts canonic domain name in IDN format to unicode string
diff --git a/contrib/unbound/libunbound/ubsyms.def b/contrib/unbound/libunbound/ubsyms.def
index d03a84b..0d8e6af 100644
--- a/contrib/unbound/libunbound/ubsyms.def
+++ b/contrib/unbound/libunbound/ubsyms.def
@@ -6,6 +6,7 @@ ub_ctx_async
ub_ctx_config
ub_ctx_create
ub_ctx_create_event
+ub_ctx_create_ub_event
ub_ctx_data_add
ub_ctx_data_remove
ub_ctx_debuglevel
diff --git a/contrib/unbound/libunbound/unbound-event.h b/contrib/unbound/libunbound/unbound-event.h
index b80de38..432750d 100644
--- a/contrib/unbound/libunbound/unbound-event.h
+++ b/contrib/unbound/libunbound/unbound-event.h
@@ -36,20 +36,21 @@
/**
* \file
*
- * This file contains the unbound interface for use with libevent.
- * You have to use the same libevent that unbound was compiled with,
- * otherwise it wouldn't work, the event and event_base structures would
- * be different. If unbound is compiled without libevent support then
- * this header file is not supposed to be installed on the system.
+ * This file contains the unbound interface for use with user defined
+ * pluggable event bases.
*
- * Use ub_ctx_create_event_base() to create an unbound context that uses
- * the event base that you have made. Then, use the ub_resolve_event call
- * to add DNS resolve queries to the context. Those then run when you
- * call event_dispatch() on your event_base, and when they are done you
- * get a function callback.
+ * Use ub_ctx_create_event_ub_base() to create an unbound context that uses
+ * the user provided event base API. Then, use the ub_resolve_event call
+ * to add DNS resolve queries to the context. Those then run whith the
+ * provided event_base, and when they are done you get a function callback.
*
* This method does not fork another process or create a thread, the effort
- * is done by the unbound state machines that are connected to the event_base.
+ * is done by the unbound state machines that are connected to the event base.
+ *
+ * It is also possible to provide a libevent based event base by using
+ * ub_ctx_create_event_base(). But you have to use the same libevent that
+ * unbound was compiled with, otherwise it wouldn't work, the event and
+ * event_base structures would be different.
*/
#ifndef _UB_UNBOUND_EVENT_H
#define _UB_UNBOUND_EVENT_H
@@ -62,12 +63,136 @@ struct ub_ctx;
struct ub_result;
struct event_base;
+/** event timeout */
+#define UB_EV_TIMEOUT 0x01
+/** event fd readable */
+#define UB_EV_READ 0x02
+/** event fd writable */
+#define UB_EV_WRITE 0x04
+/** event signal */
+#define UB_EV_SIGNAL 0x08
+/** event must persist */
+#define UB_EV_PERSIST 0x10
+
+/** magic number to identify this version of the pluggable event api */
+#define UB_EVENT_MAGIC 0x44d74d78
+
+struct ub_event;
+struct ub_event_base;
+struct timeval;
+
+/**
+ * The Virtual Method Table for and ub_event_base "object"
+ */
+struct ub_event_base_vmt {
+ /** Destructor for the ub_event_base object,
+ * (not called by libunbound) */
+ void (*free)(struct ub_event_base*);
+ /** Run the event loop
+ * (not called by libunbound when using ub_resolve_event) */
+ int (*dispatch)(struct ub_event_base*);
+ /** Exit the given event loop */
+ int (*loopexit)(struct ub_event_base*, struct timeval*);
+ /** Instantiate a new ub_event associated with this event base */
+ struct ub_event* (*new_event)(struct ub_event_base*,
+ int fd, short bits, void (*cb)(int, short, void*), void* arg);
+ /** Instantiate a new signal associated with this event base,
+ * (not called by libunbound) */
+ struct ub_event* (*new_signal)(struct ub_event_base*, int fd,
+ void (*cb)(int, short, void*), void* arg);
+ /** Create a new ub_event associated with the given wsaevent,
+ * (not called by libunbound) */
+ struct ub_event* (*winsock_register_wsaevent)(struct ub_event_base*,
+ void* wsaevent, void (*cb)(int, short, void*), void* arg);
+};
+
+/**
+ * A user defined pluggable event base is registered by providing a
+ * ub_event_base "object" with the ub_ctx_create_ub_event() function.
+ * The magic number must be correct and the Virtual Method Table must be
+ * fully equipped providing the event base API to be used by libunbound.
+ */
+struct ub_event_base {
+ /** magic must be UB_EVENT_MAGIC (0x44d74d78) */
+ unsigned long magic;
+ /** Virtual Method Table for ub_event_base */
+ struct ub_event_base_vmt* vmt;
+};
+
+/**
+ * The Virtual Method Table for and ub_event "object"
+ */
+struct ub_event_vmt {
+ /** Add event bits for this event to fire on.
+ * The event will be deactivated before this function is called. */
+ void (*add_bits)(struct ub_event*, short);
+ /** Configure the event so it will not longer fire on given bits
+ * The event will be deactivated before this function is called. */
+ void (*del_bits)(struct ub_event*, short);
+ /** Change or set the file descriptor on the event
+ * The event will be deactivated before this function is called. */
+ void (*set_fd)(struct ub_event*, int);
+ /** Destructor for the ub_event object */
+ void (*free)(struct ub_event*);
+ /** Activate the event. The given timeval is an timeout value. */
+ int (*add)(struct ub_event*, struct timeval*);
+ /** Deactivate the event */
+ int (*del)(struct ub_event*);
+ /** Reconfigure and activate a timeout event */
+ int (*add_timer)(struct ub_event*, struct ub_event_base*,
+ void (*cb)(int, short, void*), void* arg, struct timeval*);
+ /** Deactivate the timeout event */
+ int (*del_timer)(struct ub_event*);
+ /** Activate a signal event (not called by libunbound). */
+ int (*add_signal)(struct ub_event*, struct timeval*);
+ /** Deactivate a signal event (not called by libunbound). */
+ int (*del_signal)(struct ub_event*);
+ /** Destructor for a ub_event associated with a wsaevent,
+ * (not called by libunbound)
+ */
+ void (*winsock_unregister_wsaevent)(struct ub_event* ev);
+ /** Libunbound will signal the eventloop when a TCP windows socket
+ * will block on next read or write (given by the eventbits), to work
+ * around edge trigger event behaviour of select on windows with TCP.
+ */
+ void (*winsock_tcp_wouldblock)(struct ub_event*, int eventbit);
+};
+
+/**
+ * An "object" comprising a user defined pluggable event.
+ * The magic number must be correct and the Virtual Method Table must be
+ * fully equipped providing the ub_event API to be used by libunbound.
+ */
+struct ub_event {
+ /** magic must be UB_EVENT_MAGIC (0x44d74d78) */
+ unsigned long magic;
+ /** Virtual Method Table for ub_event */
+ struct ub_event_vmt* vmt;
+};
+
typedef void (*ub_event_callback_t)(void*, int, void*, int, int, char*);
/**
* Create a resolving and validation context.
* The information from /etc/resolv.conf and /etc/hosts is not utilised by
* default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them.
+ * @param base: the pluggable event base that the caller has created.
+ * The unbound context uses this event base.
+ * @return a new context. default initialisation.
+ * returns NULL on error.
+ * You must use ub_resolve_event with this context.
+ * Do not call ub_ctx_async, ub_poll, ub_wait, ub_process, this is all done
+ * with the event_base. Setup the options you like with the other functions.
+ */
+struct ub_ctx* ub_ctx_create_ub_event(struct ub_event_base* base);
+
+/**
+ * Create a resolving and validation context.
+ * The information from /etc/resolv.conf and /etc/hosts is not utilised by
+ * default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them.
+ * You have to use the same libevent that unbound was compiled with,
+ * otherwise it wouldn't work, the event and event_base structures would
+ * be different.
* @param base: the event base that the caller has created. The unbound
* context uses this event base.
* @return a new context. default initialisation.
@@ -79,7 +204,10 @@ typedef void (*ub_event_callback_t)(void*, int, void*, int, int, char*);
struct ub_ctx* ub_ctx_create_event(struct event_base* base);
/**
- * Set a new event_base on a context created with ub_ctx_create_event.
+ * Set a new libevent event_base on a context created with ub_ctx_create_event.
+ * You have to use the same libevent that unbound was compiled with,
+ * otherwise it wouldn't work, the event and event_base structures would
+ * be different.
* Any outbound queries will be canceled.
* @param ctx the ub_ctx to update. Must have been created with ub_ctx_create_event
* @param base the new event_base to attach to the ctx
diff --git a/contrib/unbound/libunbound/worker.h b/contrib/unbound/libunbound/worker.h
index a531501..b8d8dd8 100644
--- a/contrib/unbound/libunbound/worker.h
+++ b/contrib/unbound/libunbound/worker.h
@@ -48,6 +48,7 @@ struct comm_reply;
struct comm_point;
struct module_qstate;
struct tube;
+struct edns_option;
/**
* Worker service routine to send serviced queries to authoritative servers.
@@ -59,6 +60,7 @@ struct tube;
* @param dnssec: if set, EDNS record will have DO bit set.
* @param want_dnssec: signatures needed.
* @param nocaps: ignore capsforid(if in config), do not perturb qname.
+ * @param opt_list: EDNS options on outgoing packet.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: delegation point name.
@@ -69,9 +71,9 @@ struct tube;
*/
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
- int want_dnssec, int nocaps, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* zone, size_t zonelen,
- struct module_qstate* q);
+ int want_dnssec, int nocaps, struct edns_option* opt_list,
+ struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
+ size_t zonelen, struct module_qstate* q);
/** process incoming replies from the network */
int libworker_handle_reply(struct comm_point* c, void* arg, int error,
@@ -114,6 +116,7 @@ void worker_sighandler(int sig, void* arg);
* @param dnssec: if set, EDNS record will have DO bit set.
* @param want_dnssec: signatures needed.
* @param nocaps: ignore capsforid(if in config), do not perturb qname.
+ * @param opt_list: EDNS options on outgoing packet.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: wireformat dname of the zone.
@@ -124,9 +127,9 @@ void worker_sighandler(int sig, void* arg);
*/
struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
- int want_dnssec, int nocaps, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* zone, size_t zonelen,
- struct module_qstate* q);
+ int want_dnssec, int nocaps, struct edns_option* opt_list,
+ struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
+ size_t zonelen, struct module_qstate* q);
/**
* process control messages from the main thread. Frees the control
diff --git a/contrib/unbound/services/cache/dns.c b/contrib/unbound/services/cache/dns.c
index e14e636..84db7a7 100644
--- a/contrib/unbound/services/cache/dns.c
+++ b/contrib/unbound/services/cache/dns.c
@@ -795,6 +795,12 @@ dns_cache_lookup(struct module_env* env,
dname_remove_label(&k.qname, &k.qname_len);
h = query_info_hash(&k, flags);
e = slabhash_lookup(env->msg_cache, h, &k, 0);
+ if(!e && k.qtype != LDNS_RR_TYPE_NS &&
+ env->cfg->qname_minimisation) {
+ k.qtype = LDNS_RR_TYPE_NS;
+ h = query_info_hash(&k, flags);
+ e = slabhash_lookup(env->msg_cache, h, &k, 0);
+ }
if(e) {
struct reply_info* data = (struct reply_info*)e->data;
struct dns_msg* msg;
@@ -810,6 +816,7 @@ dns_cache_lookup(struct module_env* env,
}
lock_rw_unlock(&e->lock);
}
+ k.qtype = qtype;
}
/* fill common RR types for ANY response to avoid requery */
diff --git a/contrib/unbound/services/listen_dnsport.c b/contrib/unbound/services/listen_dnsport.c
index be63439..6637483 100644
--- a/contrib/unbound/services/listen_dnsport.c
+++ b/contrib/unbound/services/listen_dnsport.c
@@ -43,6 +43,9 @@
# include <sys/types.h>
#endif
#include <sys/time.h>
+#ifdef USE_TCP_FASTOPEN
+#include <netinet/tcp.h>
+#endif
#include "services/listen_dnsport.h"
#include "services/outside_network.h"
#include "util/netevent.h"
@@ -96,10 +99,11 @@ verbose_print_addr(struct addrinfo *addr)
int
create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto,
- int rcv, int snd, int listen, int* reuseport, int transparent)
+ int rcv, int snd, int listen, int* reuseport, int transparent,
+ int freebind)
{
int s;
-#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY)
+#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
int on=1;
#endif
#ifdef IPV6_MTU
@@ -117,6 +121,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
(void)transparent;
#endif
+#if !defined(IP_FREEBIND)
+ (void)freebind;
+#endif
if((s = socket(family, socktype, 0)) == -1) {
*inuse = 0;
#ifndef USE_WINSOCK
@@ -190,12 +197,21 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
#elif defined(IP_BINDANY)
if (transparent &&
setsockopt(s, (family==AF_INET6? IPPROTO_IPV6:IPPROTO_IP),
- IP_BINDANY, (void*)&on, (socklen_t)sizeof(on)) < 0) {
- log_warn("setsockopt(.. IP_BINDANY ..) failed: %s",
- strerror(errno));
+ (family == AF_INET6? IPV6_BINDANY:IP_BINDANY),
+ (void*)&on, (socklen_t)sizeof(on)) < 0) {
+ log_warn("setsockopt(.. IP%s_BINDANY ..) failed: %s",
+ (family==AF_INET6?"V6":""), strerror(errno));
}
#endif /* IP_TRANSPARENT || IP_BINDANY */
}
+#ifdef IP_FREEBIND
+ if(freebind &&
+ setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on,
+ (socklen_t)sizeof(on)) < 0) {
+ log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s",
+ strerror(errno));
+ }
+#endif /* IP_FREEBIND */
if(rcv) {
#ifdef SO_RCVBUF
int got;
@@ -490,15 +506,21 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
int
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
- int* reuseport, int transparent, int mss)
+ int* reuseport, int transparent, int mss, int freebind)
{
int s;
-#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT)
+#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
int on = 1;
#endif
-#ifndef IP_TRANSPARENT
+#ifdef USE_TCP_FASTOPEN
+ int qlen;
+#endif
+#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
(void)transparent;
#endif
+#if !defined(IP_FREEBIND)
+ (void)freebind;
+#endif
verbose_print_addr(addr);
*noproto = 0;
if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
@@ -553,6 +575,13 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
return -1;
}
#endif /* SO_REUSEADDR */
+#ifdef IP_FREEBIND
+ if (freebind && setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on,
+ (socklen_t)sizeof(on)) < 0) {
+ log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s",
+ strerror(errno));
+ }
+#endif /* IP_FREEBIND */
#ifdef SO_REUSEPORT
/* try to set SO_REUSEPORT so that incoming
* connections are distributed evenly among the receiving threads.
@@ -599,7 +628,15 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
log_warn("setsockopt(.. IP_TRANSPARENT ..) failed: %s",
strerror(errno));
}
-#endif /* IP_TRANSPARENT */
+#elif defined(IP_BINDANY)
+ if (transparent &&
+ setsockopt(s, (addr->ai_family==AF_INET6? IPPROTO_IPV6:IPPROTO_IP),
+ (addr->ai_family == AF_INET6? IPV6_BINDANY:IP_BINDANY),
+ (void*)&on, (socklen_t)sizeof(on)) < 0) {
+ log_warn("setsockopt(.. IP%s_BINDANY ..) failed: %s",
+ (addr->ai_family==AF_INET6?"V6":""), strerror(errno));
+ }
+#endif /* IP_TRANSPARENT || IP_BINDANY */
if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
#ifndef USE_WINSOCK
/* detect freebsd jail with no ipv6 permission */
@@ -638,6 +675,22 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
#endif
return -1;
}
+#ifdef USE_TCP_FASTOPEN
+ /* qlen specifies how many outstanding TFO requests to allow. Limit is a defense
+ against IP spoofing attacks as suggested in RFC7413 */
+#ifdef __APPLE__
+ /* OS X implementation only supports qlen of 1 via this call. Actual
+ value is configured by the net.inet.tcp.fastopen_backlog kernel parm. */
+ qlen = 1;
+#else
+ /* 5 is recommended on linux */
+ qlen = 5;
+#endif
+ if ((setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &qlen,
+ sizeof(qlen))) == -1 ) {
+ log_err("Setting TCP Fast Open as server failed: %s", strerror(errno));
+ }
+#endif
return s;
}
@@ -651,7 +704,7 @@ create_local_accept_sock(const char *path, int* noproto)
verbose(VERB_ALGO, "creating unix socket %s", path);
#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
/* this member exists on BSDs, not Linux */
- usock.sun_len = (socklen_t)sizeof(usock);
+ usock.sun_len = (unsigned)sizeof(usock);
#endif
usock.sun_family = AF_LOCAL;
/* length is 92-108, 104 on FreeBSD */
@@ -704,7 +757,7 @@ create_local_accept_sock(const char *path, int* noproto)
static int
make_sock(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
- int* reuseport, int transparent, int tcp_mss)
+ int* reuseport, int transparent, int tcp_mss, int freebind)
{
struct addrinfo *res = NULL;
int r, s, inuse, noproto;
@@ -732,7 +785,7 @@ make_sock(int stype, const char* ifname, const char* port,
s = create_udp_sock(res->ai_family, res->ai_socktype,
(struct sockaddr*)res->ai_addr, res->ai_addrlen,
v6only, &inuse, &noproto, (int)rcv, (int)snd, 1,
- reuseport, transparent);
+ reuseport, transparent, freebind);
if(s == -1 && inuse) {
log_err("bind: address already in use");
} else if(s == -1 && noproto && hints->ai_family == AF_INET6){
@@ -740,7 +793,7 @@ make_sock(int stype, const char* ifname, const char* port,
}
} else {
s = create_tcp_accept_sock(res, v6only, &noproto, reuseport,
- transparent, tcp_mss);
+ transparent, tcp_mss, freebind);
if(s == -1 && noproto && hints->ai_family == AF_INET6){
*noip6 = 1;
}
@@ -753,7 +806,7 @@ make_sock(int stype, const char* ifname, const char* port,
static int
make_sock_port(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
- int* reuseport, int transparent, int tcp_mss)
+ int* reuseport, int transparent, int tcp_mss, int freebind)
{
char* s = strchr(ifname, '@');
if(s) {
@@ -775,10 +828,10 @@ make_sock_port(int stype, const char* ifname, const char* port,
(void)strlcpy(p, s+1, sizeof(p));
p[strlen(s+1)]=0;
return make_sock(stype, newif, p, hints, v6only, noip6,
- rcv, snd, reuseport, transparent, tcp_mss);
+ rcv, snd, reuseport, transparent, tcp_mss, freebind);
}
return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
- reuseport, transparent, tcp_mss);
+ reuseport, transparent, tcp_mss, freebind);
}
/**
@@ -874,13 +927,14 @@ set_recvpktinfo(int s, int family)
* set to false on exit if reuseport failed due to no kernel support.
* @param transparent: set IP_TRANSPARENT socket option.
* @param tcp_mss: maximum segment size of tcp socket. default if zero.
+ * @param freebind: set IP_FREEBIND socket option.
* @return: returns false on error.
*/
static int
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
struct addrinfo *hints, const char* port, struct listen_port** list,
size_t rcv, size_t snd, int ssl_port, int* reuseport, int transparent,
- int tcp_mss)
+ int tcp_mss, int freebind)
{
int s, noip6=0;
if(!do_udp && !do_tcp)
@@ -888,7 +942,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if(do_auto) {
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
- tcp_mss)) == -1) {
+ tcp_mss, freebind)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@@ -916,7 +970,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
/* regular udp socket */
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
- tcp_mss)) == -1) {
+ tcp_mss, freebind)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@@ -937,7 +991,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
atoi(strchr(ifname, '@')+1) == ssl_port) ||
(!strchr(ifname, '@') && atoi(port) == ssl_port));
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
- &noip6, 0, 0, reuseport, transparent, tcp_mss)) == -1) {
+ &noip6, 0, 0, reuseport, transparent, tcp_mss,
+ freebind)) == -1) {
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
return 1;
@@ -1095,7 +1150,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, reuseport,
cfg->ip_transparent,
- cfg->tcp_mss)) {
+ cfg->tcp_mss, cfg->ip_freebind)) {
listening_ports_free(list);
return NULL;
}
@@ -1108,7 +1163,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, reuseport,
cfg->ip_transparent,
- cfg->tcp_mss)) {
+ cfg->tcp_mss, cfg->ip_freebind)) {
listening_ports_free(list);
return NULL;
}
@@ -1123,7 +1178,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, reuseport,
cfg->ip_transparent,
- cfg->tcp_mss)) {
+ cfg->tcp_mss, cfg->ip_freebind)) {
listening_ports_free(list);
return NULL;
}
@@ -1136,7 +1191,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, reuseport,
cfg->ip_transparent,
- cfg->tcp_mss)) {
+ cfg->tcp_mss, cfg->ip_freebind)) {
listening_ports_free(list);
return NULL;
}
diff --git a/contrib/unbound/services/listen_dnsport.h b/contrib/unbound/services/listen_dnsport.h
index 3a46e41..fbaa483 100644
--- a/contrib/unbound/services/listen_dnsport.h
+++ b/contrib/unbound/services/listen_dnsport.h
@@ -190,11 +190,12 @@ void listen_start_accept(struct listen_dnsport* listen);
* @param reuseport: if nonNULL and true, try to set SO_REUSEPORT on
* listening UDP port. Set to false on return if it failed to do so.
* @param transparent: set IP_TRANSPARENT socket option.
+ * @param freebind: set IP_FREEBIND socket option.
* @return: the socket. -1 on error.
*/
int create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv,
- int snd, int listen, int* reuseport, int transparent);
+ int snd, int listen, int* reuseport, int transparent, int freebind);
/**
* Create and bind TCP listening socket
@@ -205,10 +206,11 @@ int create_udp_sock(int family, int socktype, struct sockaddr* addr,
* listening UDP port. Set to false on return if it failed to do so.
* @param transparent: set IP_TRANSPARENT socket option.
* @param mss: maximum segment size of the socket. if zero, leaves the default.
+ * @param freebind: set IP_FREEBIND socket option.
* @return: the socket. -1 on error.
*/
int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
- int* reuseport, int transparent, int mss);
+ int* reuseport, int transparent, int mss, int freebind);
/**
* Create and bind local listening socket
diff --git a/contrib/unbound/services/localzone.c b/contrib/unbound/services/localzone.c
index 1fcac97..9bc2609 100644
--- a/contrib/unbound/services/localzone.c
+++ b/contrib/unbound/services/localzone.c
@@ -94,6 +94,7 @@ local_zone_delete(struct local_zone* z)
lock_rw_destroy(&z->lock);
regional_destroy(z->region);
free(z->name);
+ free(z->taglist);
free(z);
}
@@ -171,6 +172,7 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
{
struct local_zone* z = local_zone_create(nm, len, labs, t, c);
if(!z) {
+ free(nm);
log_err("out of memory");
return NULL;
}
@@ -182,8 +184,11 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
log_warn("duplicate local-zone");
lock_rw_unlock(&z->lock);
local_zone_delete(z);
+ /* find the correct zone, so not an error for duplicate */
+ z = local_zones_find(zones, nm, len, labs, c);
+ lock_rw_wrlock(&z->lock);
lock_rw_unlock(&zones->lock);
- return NULL;
+ return z;
}
lock_rw_unlock(&zones->lock);
return z;
@@ -506,6 +511,123 @@ lz_enter_rr_str(struct local_zones* zones, const char* rr)
return r;
}
+/** enter tagstring into zone */
+static int
+lz_enter_zone_tag(struct local_zones* zones, char* zname, uint8_t* list,
+ size_t len, uint16_t rr_class)
+{
+ uint8_t dname[LDNS_MAX_DOMAINLEN+1];
+ size_t dname_len = sizeof(dname);
+ int dname_labs, r = 0;
+ struct local_zone* z;
+
+ if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) {
+ log_err("cannot parse zone name in local-zone-tag: %s", zname);
+ return 0;
+ }
+ dname_labs = dname_count_labels(dname);
+
+ lock_rw_rdlock(&zones->lock);
+ z = local_zones_find(zones, dname, dname_len, dname_labs, rr_class);
+ if(!z) {
+ lock_rw_unlock(&zones->lock);
+ log_err("no local-zone for tag %s", zname);
+ return 0;
+ }
+ lock_rw_wrlock(&z->lock);
+ lock_rw_unlock(&zones->lock);
+ free(z->taglist);
+ z->taglist = memdup(list, len);
+ z->taglen = len;
+ if(z->taglist)
+ r = 1;
+ lock_rw_unlock(&z->lock);
+ return r;
+}
+
+/** enter override into zone */
+static int
+lz_enter_override(struct local_zones* zones, char* zname, char* netblock,
+ char* type, uint16_t rr_class)
+{
+ uint8_t dname[LDNS_MAX_DOMAINLEN+1];
+ size_t dname_len = sizeof(dname);
+ int dname_labs;
+ struct sockaddr_storage addr;
+ int net;
+ socklen_t addrlen;
+ struct local_zone* z;
+ enum localzone_type t;
+
+ /* parse zone name */
+ if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) {
+ log_err("cannot parse zone name in local-zone-override: %s %s",
+ zname, netblock);
+ return 0;
+ }
+ dname_labs = dname_count_labels(dname);
+
+ /* parse netblock */
+ if(!netblockstrtoaddr(netblock, UNBOUND_DNS_PORT, &addr, &addrlen,
+ &net)) {
+ log_err("cannot parse netblock in local-zone-override: %s %s",
+ zname, netblock);
+ return 0;
+ }
+
+ /* parse zone type */
+ if(!local_zone_str2type(type, &t)) {
+ log_err("cannot parse type in local-zone-override: %s %s %s",
+ zname, netblock, type);
+ return 0;
+ }
+
+ /* find localzone entry */
+ lock_rw_rdlock(&zones->lock);
+ z = local_zones_find(zones, dname, dname_len, dname_labs, rr_class);
+ if(!z) {
+ lock_rw_unlock(&zones->lock);
+ log_err("no local-zone for local-zone-override %s", zname);
+ return 0;
+ }
+ lock_rw_wrlock(&z->lock);
+ lock_rw_unlock(&zones->lock);
+
+ /* create netblock addr_tree if not present yet */
+ if(!z->override_tree) {
+ z->override_tree = (struct rbtree_t*)regional_alloc_zero(
+ z->region, sizeof(*z->override_tree));
+ if(!z->override_tree) {
+ lock_rw_unlock(&z->lock);
+ log_err("out of memory");
+ return 0;
+ }
+ addr_tree_init(z->override_tree);
+ }
+ /* add new elem to tree */
+ if(z->override_tree) {
+ struct local_zone_override* n;
+ n = (struct local_zone_override*)regional_alloc_zero(
+ z->region, sizeof(*n));
+ if(!n) {
+ lock_rw_unlock(&z->lock);
+ log_err("out of memory");
+ return 0;
+ }
+ n->type = t;
+ if(!addr_tree_insert(z->override_tree,
+ (struct addr_tree_node*)n, &addr, addrlen, net)) {
+ lock_rw_unlock(&z->lock);
+ log_err("duplicate local-zone-override %s %s",
+ zname, netblock);
+ return 1;
+ }
+ }
+
+ lock_rw_unlock(&z->lock);
+ return 1;
+}
+
/** parse local-zone: statements */
static int
lz_enter_zones(struct local_zones* zones, struct config_file* cfg)
@@ -684,6 +806,19 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg)
return 1;
}
+/** parse local-zone-override: statements */
+static int
+lz_enter_overrides(struct local_zones* zones, struct config_file* cfg)
+{
+ struct config_str3list* p;
+ for(p = cfg->local_zone_overrides; p; p = p->next) {
+ if(!lz_enter_override(zones, p->str, p->str2, p->str3,
+ LDNS_RR_CLASS_IN))
+ return 0;
+ }
+ return 1;
+}
+
/** setup parent pointers, so that a lookup can be done for closest match */
static void
init_parents(struct local_zones* zones)
@@ -713,6 +848,9 @@ init_parents(struct local_zones* zones)
break;
}
prev = node;
+
+ if(node->override_tree)
+ addr_tree_init_parents(node->override_tree);
lock_rw_unlock(&node->lock);
}
lock_rw_unlock(&zones->lock);
@@ -800,6 +938,22 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
return 1;
}
+/** enter local-zone-tag info */
+static int
+lz_enter_zone_tags(struct local_zones* zones, struct config_file* cfg)
+{
+ struct config_strbytelist* p;
+ int c = 0;
+ for(p = cfg->local_zone_tags; p; p = p->next) {
+ if(!lz_enter_zone_tag(zones, p->str, p->str2, p->str2len,
+ LDNS_RR_CLASS_IN))
+ return 0;
+ c++;
+ }
+ if(c) verbose(VERB_ALGO, "applied tags to %d local zones", c);
+ return 1;
+}
+
/** enter auth data */
static int
lz_enter_data(struct local_zones* zones, struct config_file* cfg)
@@ -835,6 +989,10 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
if(!lz_enter_defaults(zones, cfg)) {
return 0;
}
+ /* enter local zone overrides */
+ if(!lz_enter_overrides(zones, cfg)) {
+ return 0;
+ }
/* create implicit transparent zone from data. */
if(!lz_setup_implicit(zones, cfg)) {
return 0;
@@ -842,6 +1000,10 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
/* setup parent ptrs for lookup during data entry */
init_parents(zones);
+ /* insert local zone tags */
+ if(!lz_enter_zone_tags(zones, cfg)) {
+ return 0;
+ }
/* insert local data */
if(!lz_enter_data(zones, cfg)) {
return 0;
@@ -855,33 +1017,41 @@ struct local_zone*
local_zones_lookup(struct local_zones* zones,
uint8_t* name, size_t len, int labs, uint16_t dclass)
{
+ return local_zones_tags_lookup(zones, name, len, labs,
+ dclass, NULL, 0, 1);
+}
+
+struct local_zone*
+local_zones_tags_lookup(struct local_zones* zones,
+ uint8_t* name, size_t len, int labs, uint16_t dclass,
+ uint8_t* taglist, size_t taglen, int ignoretags)
+{
rbnode_t* res = NULL;
struct local_zone *result;
struct local_zone key;
+ int m;
key.node.key = &key;
key.dclass = dclass;
key.name = name;
key.namelen = len;
key.namelabs = labs;
- if(rbtree_find_less_equal(&zones->ztree, &key, &res)) {
- /* exact */
- return (struct local_zone*)res;
- } else {
- /* smaller element (or no element) */
- int m;
- result = (struct local_zone*)res;
- if(!result || result->dclass != dclass)
- return NULL;
- /* count number of labels matched */
- (void)dname_lab_cmp(result->name, result->namelabs, key.name,
- key.namelabs, &m);
- while(result) { /* go up until qname is subdomain of zone */
- if(result->namelabs <= m)
- break;
- result = result->parent;
- }
- return result;
- }
+ rbtree_find_less_equal(&zones->ztree, &key, &res);
+ result = (struct local_zone*)res;
+ /* exact or smaller element (or no element) */
+ if(!result || result->dclass != dclass)
+ return NULL;
+ /* count number of labels matched */
+ (void)dname_lab_cmp(result->name, result->namelabs, key.name,
+ key.namelabs, &m);
+ while(result) { /* go up until qname is zone or subdomain of zone */
+ if(result->namelabs <= m)
+ if(ignoretags || !result->taglist ||
+ taglist_intersect(result->taglist,
+ result->taglen, taglist, taglen))
+ break;
+ result = result->parent;
+ }
+ return result;
}
struct local_zone*
@@ -953,6 +1123,18 @@ void local_zones_print(struct local_zones* zones)
log_nametypeclass(0, "inform_deny zone",
z->name, 0, z->dclass);
break;
+ case local_zone_always_transparent:
+ log_nametypeclass(0, "always_transparent zone",
+ z->name, 0, z->dclass);
+ break;
+ case local_zone_always_refuse:
+ log_nametypeclass(0, "always_refuse zone",
+ z->name, 0, z->dclass);
+ break;
+ case local_zone_always_nxdomain:
+ log_nametypeclass(0, "always_nxdomain zone",
+ z->name, 0, z->dclass);
+ break;
default:
log_nametypeclass(0, "badtyped zone",
z->name, 0, z->dclass);
@@ -986,7 +1168,8 @@ local_encode(struct query_info* qinfo, struct edns_data* edns,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
- if(!reply_info_answer_encode(qinfo, &rep,
+ if(!edns_opt_inplace_reply(edns, temp) ||
+ !reply_info_answer_encode(qinfo, &rep,
*(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2),
buf, 0, 0, temp, udpsize, edns,
@@ -997,11 +1180,99 @@ local_encode(struct query_info* qinfo, struct edns_data* edns,
return 1;
}
+/** find local data tag string match for the given type in the list */
+static int
+find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
+ struct ub_packed_rrset_key* r, struct regional* temp,
+ uint8_t* zname, size_t zlen)
+{
+ struct config_strlist* p;
+ char buf[65536];
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ size_t len;
+ int res;
+ struct packed_rrset_data* d;
+ for(p=list; p; p=p->next) {
+ len = sizeof(rr);
+ /* does this element match the type? */
+ snprintf(buf, sizeof(buf), ". %s", p->str);
+ res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600,
+ zname, zlen, NULL, 0);
+ if(res != 0)
+ /* parse errors are already checked before, in
+ * acllist check_data, skip this for robustness */
+ continue;
+ if(len < 1 /* . */ + 8 /* typeclassttl*/ + 2 /*rdatalen*/)
+ continue;
+ if(sldns_wirerr_get_type(rr, len, 1) != qinfo->qtype)
+ continue;
+
+ /* do we have entries already? if not setup key */
+ if(r->rk.dname == NULL) {
+ r->entry.key = r;
+ r->rk.dname = qinfo->qname;
+ r->rk.dname_len = qinfo->qname_len;
+ r->rk.type = htons(qinfo->qtype);
+ r->rk.rrset_class = htons(qinfo->qclass);
+ r->rk.flags = 0;
+ d = (struct packed_rrset_data*)regional_alloc_zero(
+ temp, sizeof(struct packed_rrset_data)
+ + sizeof(size_t) + sizeof(uint8_t*) +
+ sizeof(time_t));
+ if(!d) return 0; /* out of memory */
+ r->entry.data = d;
+ d->ttl = sldns_wirerr_get_ttl(rr, len, 1);
+ d->rr_len = (size_t*)((uint8_t*)d +
+ sizeof(struct packed_rrset_data));
+ d->rr_data = (uint8_t**)&(d->rr_len[1]);
+ d->rr_ttl = (time_t*)&(d->rr_data[1]);
+ }
+ d = (struct packed_rrset_data*)r->entry.data;
+ /* add entry to the data */
+ if(d->count != 0) {
+ size_t* oldlen = d->rr_len;
+ uint8_t** olddata = d->rr_data;
+ time_t* oldttl = d->rr_ttl;
+ /* increase arrays for lookup */
+ /* this is of course slow for very many records,
+ * but most redirects are expected with few records */
+ d->rr_len = (size_t*)regional_alloc_zero(temp,
+ (d->count+1)*sizeof(size_t));
+ d->rr_data = (uint8_t**)regional_alloc_zero(temp,
+ (d->count+1)*sizeof(uint8_t*));
+ d->rr_ttl = (time_t*)regional_alloc_zero(temp,
+ (d->count+1)*sizeof(time_t));
+ if(!d->rr_len || !d->rr_data || !d->rr_ttl)
+ return 0; /* out of memory */
+ /* first one was allocated after struct d, but new
+ * ones get their own array increment alloc, so
+ * copy old content */
+ memmove(d->rr_len, oldlen, d->count*sizeof(size_t));
+ memmove(d->rr_data, olddata, d->count*sizeof(uint8_t*));
+ memmove(d->rr_ttl, oldttl, d->count*sizeof(time_t));
+ }
+
+ d->rr_len[d->count] = sldns_wirerr_get_rdatalen(rr, len, 1)+2;
+ d->rr_ttl[d->count] = sldns_wirerr_get_ttl(rr, len, 1);
+ d->rr_data[d->count] = regional_alloc_init(temp,
+ sldns_wirerr_get_rdatawl(rr, len, 1),
+ d->rr_len[d->count]);
+ if(!d->rr_data[d->count])
+ if(!d) return 0; /* out of memory */
+ d->count++;
+ }
+ if(r->rk.dname)
+ return 1;
+ return 0;
+}
+
/** answer local data match */
static int
local_data_answer(struct local_zone* z, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
- int labs, struct local_data** ldp)
+ int labs, struct local_data** ldp, enum localzone_type lz_type,
+ int tag, struct config_strlist** tag_datas, size_t tag_datas_size,
+ char** tagname, int num_tags)
{
struct local_data key;
struct local_data* ld;
@@ -1010,10 +1281,21 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo,
key.name = qinfo->qname;
key.namelen = qinfo->qname_len;
key.namelabs = labs;
- if(z->type == local_zone_redirect) {
+ if(lz_type == local_zone_redirect) {
key.name = z->name;
key.namelen = z->namelen;
key.namelabs = z->namelabs;
+ if(tag != -1 && (size_t)tag<tag_datas_size && tag_datas[tag]) {
+ struct ub_packed_rrset_key r;
+ memset(&r, 0, sizeof(r));
+ if(find_tag_datas(qinfo, tag_datas[tag], &r, temp,
+ z->name, z->namelen)) {
+ verbose(VERB_ALGO, "redirect with tag data [%d] %s",
+ tag, (tag<num_tags?tagname[tag]:"null"));
+ return local_encode(qinfo, edns, buf, temp,
+ &r, 1, LDNS_RCODE_NOERROR);
+ }
+ }
}
ld = (struct local_data*)rbtree_search(&z->data, &key.node);
*ldp = ld;
@@ -1023,7 +1305,7 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo,
lr = local_data_find_type(ld, qinfo->qtype);
if(!lr)
return 0;
- if(z->type == local_zone_redirect) {
+ if(lz_type == local_zone_redirect) {
/* convert rrset name to query name; like a wildcard */
struct ub_packed_rrset_key r = *lr->rrset;
r.rk.dname = qinfo->qname;
@@ -1043,25 +1325,28 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo,
* @param buf: buffer for answer.
* @param temp: temp region for encoding
* @param ld: local data, if NULL, no such name exists in localdata.
+ * @param lz_type: type of the local zone
* @return 1 if a reply is to be sent, 0 if not.
*/
static int
lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
- struct local_data* ld)
+ struct local_data* ld, enum localzone_type lz_type)
{
- if(z->type == local_zone_deny || z->type == local_zone_inform_deny) {
+ if(lz_type == local_zone_deny || lz_type == local_zone_inform_deny) {
/** no reply at all, signal caller by clearing buffer. */
sldns_buffer_clear(buf);
sldns_buffer_flip(buf);
return 1;
- } else if(z->type == local_zone_refuse) {
+ } else if(lz_type == local_zone_refuse
+ || lz_type == local_zone_always_refuse) {
error_encode(buf, (LDNS_RCODE_REFUSED|BIT_AA), qinfo,
*(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), edns);
return 1;
- } else if(z->type == local_zone_static ||
- z->type == local_zone_redirect) {
+ } else if(lz_type == local_zone_static ||
+ lz_type == local_zone_redirect ||
+ lz_type == local_zone_always_nxdomain) {
/* for static, reply nodata or nxdomain
* for redirect, reply nodata */
/* no additional section processing,
@@ -1069,7 +1354,8 @@ lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
* or using closest match for NSEC.
* or using closest match for returning delegation downwards
*/
- int rcode = ld?LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
+ int rcode = (ld || lz_type == local_zone_redirect)?
+ LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
if(z->soa)
return local_encode(qinfo, edns, buf, temp,
z->soa, 0, rcode);
@@ -1077,11 +1363,12 @@ lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
*(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), edns);
return 1;
- } else if(z->type == local_zone_typetransparent) {
+ } else if(lz_type == local_zone_typetransparent
+ || lz_type == local_zone_always_transparent) {
/* no NODATA or NXDOMAINS for this zone type */
return 0;
}
- /* else z->type == local_zone_transparent */
+ /* else lz_type == local_zone_transparent */
/* if the zone is transparent and the name exists, but the type
* does not, then we should make this noerror/nodata */
@@ -1115,21 +1402,70 @@ lz_inform_print(struct local_zone* z, struct query_info* qinfo,
log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
}
+static enum localzone_type
+lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
+ uint8_t *tagactions, size_t tagactionssize, enum localzone_type lzt,
+ struct comm_reply* repinfo, struct rbtree_t* override_tree, int* tag,
+ char** tagname, int num_tags)
+{
+ size_t i, j;
+ uint8_t tagmatch;
+ struct local_zone_override* lzo;
+ if(repinfo && override_tree) {
+ lzo = (struct local_zone_override*)addr_tree_lookup(
+ override_tree, &repinfo->addr, repinfo->addrlen);
+ if(lzo && lzo->type) {
+ verbose(VERB_ALGO, "local zone override to type %s",
+ local_zone_type2str(lzo->type));
+ return lzo->type;
+ }
+ }
+ if(!taglist || !taglist2)
+ return lzt;
+ for(i=0; i<taglen && i<taglen2; i++) {
+ tagmatch = (taglist[i] & taglist2[i]);
+ for(j=0; j<8 && tagmatch>0; j++) {
+ if((tagmatch & 0x1)) {
+ *tag = (int)(i*8+j);
+ verbose(VERB_ALGO, "matched tag [%d] %s",
+ *tag, (*tag<num_tags?tagname[*tag]:"null"));
+ /* does this tag have a tag action? */
+ if(i*8+j < tagactionssize && tagactions
+ && tagactions[i*8+j] != 0) {
+ verbose(VERB_ALGO, "tag action [%d] %s to type %s",
+ *tag, (*tag<num_tags?tagname[*tag]:"null"),
+ local_zone_type2str(
+ (enum localzone_type)
+ tagactions[i*8+j]));
+ return (enum localzone_type)tagactions[i*8+j];
+ }
+ return lzt;
+ }
+ tagmatch >>= 1;
+ }
+ }
+ return lzt;
+}
+
int
local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
- struct comm_reply* repinfo)
+ struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
+ uint8_t* tagactions, size_t tagactionssize,
+ struct config_strlist** tag_datas, size_t tag_datas_size,
+ char** tagname, int num_tags)
{
/* see if query is covered by a zone,
* if so: - try to match (exact) local data
* - look at zone type for negative response. */
int labs = dname_count_labels(qinfo->qname);
- struct local_data* ld;
+ struct local_data* ld = NULL;
struct local_zone* z;
- int r;
+ enum localzone_type lzt;
+ int r, tag = -1;
lock_rw_rdlock(&zones->lock);
- z = local_zones_lookup(zones, qinfo->qname,
- qinfo->qname_len, labs, qinfo->qclass);
+ z = local_zones_tags_lookup(zones, qinfo->qname,
+ qinfo->qname_len, labs, qinfo->qclass, taglist, taglen, 0);
if(!z) {
lock_rw_unlock(&zones->lock);
return 0;
@@ -1137,15 +1473,22 @@ local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
lock_rw_rdlock(&z->lock);
lock_rw_unlock(&zones->lock);
- if((z->type == local_zone_inform || z->type == local_zone_inform_deny)
+ lzt = lz_type(taglist, taglen, z->taglist, z->taglen, tagactions,
+ tagactionssize, z->type, repinfo, z->override_tree, &tag,
+ tagname, num_tags);
+
+ if((lzt == local_zone_inform || lzt == local_zone_inform_deny)
&& repinfo)
lz_inform_print(z, qinfo, repinfo);
- if(local_data_answer(z, qinfo, edns, buf, temp, labs, &ld)) {
+ if(lzt != local_zone_always_refuse && lzt != local_zone_always_transparent
+ && lzt != local_zone_always_nxdomain
+ && local_data_answer(z, qinfo, edns, buf, temp, labs, &ld, lzt,
+ tag, tag_datas, tag_datas_size, tagname, num_tags)) {
lock_rw_unlock(&z->lock);
return 1;
}
- r = lz_zone_answer(z, qinfo, edns, buf, temp, ld);
+ r = lz_zone_answer(z, qinfo, edns, buf, temp, ld, lzt);
lock_rw_unlock(&z->lock);
return r;
}
@@ -1162,6 +1505,9 @@ const char* local_zone_type2str(enum localzone_type t)
case local_zone_nodefault: return "nodefault";
case local_zone_inform: return "inform";
case local_zone_inform_deny: return "inform_deny";
+ case local_zone_always_transparent: return "always_transparent";
+ case local_zone_always_refuse: return "always_refuse";
+ case local_zone_always_nxdomain: return "always_nxdomain";
}
return "badtyped";
}
@@ -1184,6 +1530,12 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
*t = local_zone_inform;
else if(strcmp(type, "inform_deny") == 0)
*t = local_zone_inform_deny;
+ else if(strcmp(type, "always_transparent") == 0)
+ *t = local_zone_always_transparent;
+ else if(strcmp(type, "always_refuse") == 0)
+ *t = local_zone_always_refuse;
+ else if(strcmp(type, "always_nxdomain") == 0)
+ *t = local_zone_always_nxdomain;
else return 0;
return 1;
}
@@ -1220,7 +1572,10 @@ struct local_zone* local_zones_add_zone(struct local_zones* zones,
{
/* create */
struct local_zone* z = local_zone_create(name, len, labs, tp, dclass);
- if(!z) return NULL;
+ if(!z) {
+ free(name);
+ return NULL;
+ }
lock_rw_wrlock(&z->lock);
/* find the closest parent */
diff --git a/contrib/unbound/services/localzone.h b/contrib/unbound/services/localzone.h
index 3d62a69..69fdbee 100644
--- a/contrib/unbound/services/localzone.h
+++ b/contrib/unbound/services/localzone.h
@@ -43,6 +43,7 @@
#define SERVICES_LOCALZONE_H
#include "util/rbtree.h"
#include "util/locks.h"
+#include "util/storage/dnstree.h"
struct ub_packed_rrset_key;
struct regional;
struct config_file;
@@ -50,6 +51,7 @@ struct edns_data;
struct query_info;
struct sldns_buffer;
struct comm_reply;
+struct config_strlist;
/**
* Local zone type
@@ -75,7 +77,13 @@ enum localzone_type {
/** log client address, but no block (transparent) */
local_zone_inform,
/** log client address, and block (drop) */
- local_zone_inform_deny
+ local_zone_inform_deny,
+ /** resolve normally, even when there is local data */
+ local_zone_always_transparent,
+ /** answer with error, even when there is local data */
+ local_zone_always_refuse,
+ /** answer with nxdomain, even when there is local data */
+ local_zone_always_nxdomain
};
/**
@@ -115,6 +123,13 @@ struct local_zone {
/** how to process zone */
enum localzone_type type;
+ /** tag bitlist */
+ uint8_t* taglist;
+ /** length of the taglist (in bytes) */
+ size_t taglen;
+ /** netblock addr_tree with struct local_zone_override information
+ * or NULL if there are no override elements */
+ struct rbtree_t* override_tree;
/** in this region the zone's data is allocated.
* the struct local_zone itself is malloced. */
@@ -154,6 +169,16 @@ struct local_rrset {
};
/**
+ * Local zone override information
+ */
+struct local_zone_override {
+ /** node in addrtree */
+ struct addr_tree_node node;
+ /** override for local zone type */
+ enum localzone_type type;
+};
+
+/**
* Create local zones storage
* @return new struct or NULL on error.
*/
@@ -198,6 +223,24 @@ int local_data_cmp(const void* d1, const void* d2);
void local_zone_delete(struct local_zone* z);
/**
+ * Lookup zone that contains the given name, class and taglist.
+ * User must lock the tree or result zone.
+ * @param zones: the zones tree
+ * @param name: dname to lookup
+ * @param len: length of name.
+ * @param labs: labelcount of name.
+ * @param dclass: class to lookup.
+ * @param taglist: taglist to lookup.
+ * @param taglen: lenth of taglist.
+ * @param ignoretags: lookup zone by name and class, regardless the
+ * local-zone's tags.
+ * @return closest local_zone or NULL if no covering zone is found.
+ */
+struct local_zone* local_zones_tags_lookup(struct local_zones* zones,
+ uint8_t* name, size_t len, int labs, uint16_t dclass,
+ uint8_t* taglist, size_t taglen, int ignoretags);
+
+/**
* Lookup zone that contains the given name, class.
* User must lock the tree or result zone.
* @param zones: the zones tree
@@ -226,13 +269,24 @@ void local_zones_print(struct local_zones* zones);
* @param buf: buffer with query ID and flags, also for reply.
* @param temp: temporary storage region.
* @param repinfo: source address for checks. may be NULL.
+ * @param taglist: taglist for checks. May be NULL.
+ * @param taglen: length of the taglist.
+ * @param tagactions: local zone actions for tags. May be NULL.
+ * @param tagactionssize: length of the tagactions.
+ * @param tag_datas: array per tag of strlist with rdata strings. or NULL.
+ * @param tag_datas_size: size of tag_datas array.
+ * @param tagname: array of tag name strings (for debug output).
+ * @param num_tags: number of items in tagname array.
* @return true if answer is in buffer. false if query is not answered
* by authority data. If the reply should be dropped altogether, the return
* value is true, but the buffer is cleared (empty).
*/
int local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
struct edns_data* edns, struct sldns_buffer* buf, struct regional* temp,
- struct comm_reply* repinfo);
+ struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
+ uint8_t* tagactions, size_t tagactionssize,
+ struct config_strlist** tag_datas, size_t tag_datas_size,
+ char** tagname, int num_tags);
/**
* Parse the string into localzone type.
diff --git a/contrib/unbound/services/mesh.c b/contrib/unbound/services/mesh.c
index 8076874..b0434b3 100644
--- a/contrib/unbound/services/mesh.c
+++ b/contrib/unbound/services/mesh.c
@@ -315,6 +315,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
s = mesh_state_create(mesh->env, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
if(!s) {
log_err("mesh_state_create: out of memory; SERVFAIL");
+ if(!edns_opt_inplace_reply(edns, mesh->env->scratch))
+ edns->opt_list = NULL;
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
@@ -338,6 +340,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
/* add reply to s */
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo->qname)) {
log_err("mesh_new_client: out of memory; SERVFAIL");
+ if(!edns_opt_inplace_reply(edns, mesh->env->scratch))
+ edns->opt_list = NULL;
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
@@ -809,7 +813,8 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
r->edns.udp_size = EDNS_ADVERTISED_SIZE;
r->edns.ext_rcode = 0;
r->edns.bits &= EDNS_DO;
- if(!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
+ if(!edns_opt_inplace_reply(&r->edns, m->s.region) ||
+ !reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->buf, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
(int)(r->edns.bits & EDNS_DO), secure))
@@ -859,7 +864,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
if(prev && prev->qflags == r->qflags &&
prev->edns.edns_present == r->edns.edns_present &&
prev->edns.bits == r->edns.bits &&
- prev->edns.udp_size == r->edns.udp_size) {
+ prev->edns.udp_size == r->edns.udp_size &&
+ edns_opt_list_compare(prev->edns.opt_list, r->edns.opt_list)
+ == 0) {
/* if the previous reply is identical to this one, fix ID */
if(prev->query_reply.c->buffer != r->query_reply.c->buffer)
sldns_buffer_copy(r->query_reply.c->buffer,
@@ -881,7 +888,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
r->edns.ext_rcode = 0;
r->edns.bits &= EDNS_DO;
m->s.qinfo.qname = r->qname;
- if(!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
+ if(!edns_opt_inplace_reply(&r->edns, m->s.region) ||
+ !reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->query_reply.c->buffer, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
(int)(r->edns.bits & EDNS_DO), secure))
@@ -973,6 +981,12 @@ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
r->cb = cb;
r->cb_arg = cb_arg;
r->edns = *edns;
+ if(edns->opt_list) {
+ r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
+ s->s.region);
+ if(!r->edns.opt_list)
+ return 0;
+ }
r->qid = qid;
r->qflags = qflags;
r->next = s->cb_list;
@@ -990,6 +1004,12 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
return 0;
r->query_reply = *rep;
r->edns = *edns;
+ if(edns->opt_list) {
+ r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
+ s->s.region);
+ if(!r->edns.opt_list)
+ return 0;
+ }
r->qid = qid;
r->qflags = qflags;
r->start_time = *s->s.env->now_tv;
@@ -1000,7 +1020,6 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
return 0;
s->reply_list = r;
return 1;
-
}
/**
@@ -1050,6 +1069,12 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
*ev = module_event_pass;
return 1;
}
+ if(s == module_wait_subquery && mstate->sub_set.count == 0) {
+ log_err("module cannot wait for subquery, subquery list empty");
+ log_query_info(VERB_QUERY, "pass error for qstate",
+ &mstate->s.qinfo);
+ s = module_error;
+ }
if(s == module_error && mstate->s.return_rcode == LDNS_RCODE_NOERROR) {
/* error is bad, handle pass back up below */
mstate->s.return_rcode = LDNS_RCODE_SERVFAIL;
diff --git a/contrib/unbound/services/modstack.c b/contrib/unbound/services/modstack.c
index 49bb2fd..70e0666 100644
--- a/contrib/unbound/services/modstack.c
+++ b/contrib/unbound/services/modstack.c
@@ -50,6 +50,9 @@
#ifdef WITH_PYTHONMODULE
#include "pythonmod/pythonmod.h"
#endif
+#ifdef USE_CACHEDB
+#include "cachedb/cachedb.h"
+#endif
/** count number of modules (words) in the string */
static int
@@ -121,6 +124,9 @@ module_list_avail(void)
#ifdef WITH_PYTHONMODULE
"python",
#endif
+#ifdef USE_CACHEDB
+ "cachedb",
+#endif
"validator",
"iterator",
NULL};
@@ -139,6 +145,9 @@ module_funcs_avail(void)
#ifdef WITH_PYTHONMODULE
&pythonmod_get_funcblock,
#endif
+#ifdef USE_CACHEDB
+ &cachedb_get_funcblock,
+#endif
&val_get_funcblock,
&iter_get_funcblock,
NULL};
diff --git a/contrib/unbound/services/outside_network.c b/contrib/unbound/services/outside_network.c
index b5e0b2d..dd25ab3 100644
--- a/contrib/unbound/services/outside_network.c
+++ b/contrib/unbound/services/outside_network.c
@@ -122,6 +122,8 @@ serviced_cmp(const void* key1, const void* key2)
}
if((r = query_dname_compare(q1->qbuf+10, q2->qbuf+10)) != 0)
return r;
+ if((r = edns_opt_list_compare(q1->opt_list, q2->opt_list)) != 0)
+ return r;
return sockaddr_cmp(&q1->addr, q1->addrlen, &q2->addr, q2->addrlen);
}
@@ -241,7 +243,33 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
return 0;
fd_set_nonblock(s);
+#ifdef USE_OSX_MSG_FASTOPEN
+ /* API for fast open is different here. We use a connectx() function and
+ then writes can happen as normal even using SSL.*/
+ /* connectx requires that the len be set in the sockaddr struct*/
+ struct sockaddr_in *addr_in = (struct sockaddr_in *)&w->addr;
+ addr_in->sin_len = w->addrlen;
+ sa_endpoints_t endpoints;
+ endpoints.sae_srcif = 0;
+ endpoints.sae_srcaddr = NULL;
+ endpoints.sae_srcaddrlen = 0;
+ endpoints.sae_dstaddr = (struct sockaddr *)&w->addr;
+ endpoints.sae_dstaddrlen = w->addrlen;
+ if (connectx(s, &endpoints, SAE_ASSOCID_ANY,
+ CONNECT_DATA_IDEMPOTENT | CONNECT_RESUME_ON_READ_WRITE,
+ NULL, 0, NULL, NULL) == -1) {
+#else /* USE_OSX_MSG_FASTOPEN*/
+#ifdef USE_MSG_FASTOPEN
+ pend->c->tcp_do_fastopen = 1;
+ /* Only do TFO for TCP in which case no connect() is required here.
+ Don't combine client TFO with SSL, since OpenSSL can't
+ currently support doing a handshake on fd that already isn't connected*/
+ if (w->outnet->sslctx && w->ssl_upstream) {
+ if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) {
+#else /* USE_MSG_FASTOPEN*/
if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) {
+#endif /* USE_MSG_FASTOPEN*/
+#endif /* USE_OSX_MSG_FASTOPEN*/
#ifndef USE_WINSOCK
#ifdef EINPROGRESS
if(errno != EINPROGRESS) {
@@ -261,6 +289,9 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
return 0;
}
}
+#ifdef USE_MSG_FASTOPEN
+ }
+#endif /* USE_MSG_FASTOPEN */
if(w->outnet->sslctx && w->ssl_upstream) {
pend->c->ssl = outgoing_ssl_fd(w->outnet->sslctx, s);
if(!pend->c->ssl) {
@@ -589,7 +620,9 @@ static int setup_if(struct port_if* pif, const char* addrstr,
pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
if(!pif->avail_ports)
return 0;
- if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen))
+ if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
+ !netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
+ &pif->addr, &pif->addrlen, &pif->pfxlen))
return 0;
pif->maxout = (int)numfd;
pif->inuse = 0;
@@ -757,6 +790,7 @@ serviced_node_del(rbnode_t* node, void* ATTR_UNUSED(arg))
struct service_callback* p = sq->cblist, *np;
free(sq->qbuf);
free(sq->zone);
+ edns_opt_list_free(sq->opt_list);
while(p) {
np = p->next;
free(p);
@@ -890,32 +924,55 @@ pending_delete(struct outside_network* outnet, struct pending* p)
free(p);
}
+static void
+sai6_putrandom(struct sockaddr_in6 *sa, int pfxlen, struct ub_randstate *rnd)
+{
+ int i, last;
+ if(!(pfxlen > 0 && pfxlen < 128))
+ return;
+ for(i = 0; i < (128 - pfxlen) / 8; i++) {
+ sa->sin6_addr.s6_addr[15-i] = (uint8_t)ub_random_max(rnd, 256);
+ }
+ last = pfxlen & 7;
+ if(last != 0) {
+ sa->sin6_addr.s6_addr[15-i] |=
+ ((0xFF >> last) & ub_random_max(rnd, 256));
+ }
+}
+
/**
* Try to open a UDP socket for outgoing communication.
* Sets sockets options as needed.
* @param addr: socket address.
* @param addrlen: length of address.
+ * @param pfxlen: length of network prefix (for address randomisation).
* @param port: port override for addr.
* @param inuse: if -1 is returned, this bool means the port was in use.
+ * @param rnd: random state (for address randomisation).
* @return fd or -1
*/
static int
-udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int port,
- int* inuse)
+udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
+ int port, int* inuse, struct ub_randstate* rnd)
{
int fd, noproto;
if(addr_is_ip6(addr, addrlen)) {
- struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
- sa->sin6_port = (in_port_t)htons((uint16_t)port);
+ int freebind = 0;
+ struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
+ sa.sin6_port = (in_port_t)htons((uint16_t)port);
+ if(pfxlen != 0) {
+ freebind = 1;
+ sai6_putrandom(&sa, pfxlen, rnd);
+ }
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
- (struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
- 0, 0, 0, NULL, 0);
+ (struct sockaddr*)&sa, addrlen, 1, inuse, &noproto,
+ 0, 0, 0, NULL, 0, freebind);
} else {
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
sa->sin_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET, SOCK_DGRAM,
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
- 0, 0, 0, NULL, 0);
+ 0, 0, 0, NULL, 0, 0);
}
return fd;
}
@@ -975,7 +1032,8 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
/* try to open new port, if fails, loop to try again */
log_assert(pif->inuse < pif->maxout);
portno = pif->avail_ports[my_port - pif->inuse];
- fd = udp_sockport(&pif->addr, pif->addrlen, portno, &inuse);
+ fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
+ portno, &inuse, outnet->rnd);
if(fd == -1 && !inuse) {
/* nonrecoverable error making socket */
return 0;
@@ -1219,7 +1277,8 @@ serviced_gen_query(sldns_buffer* buff, uint8_t* qname, size_t qnamelen,
/** lookup serviced query in serviced query rbtree */
static struct serviced_query*
lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
- struct sockaddr_storage* addr, socklen_t addrlen)
+ struct sockaddr_storage* addr, socklen_t addrlen,
+ struct edns_option* opt_list)
{
struct serviced_query key;
key.node.key = &key;
@@ -1229,6 +1288,7 @@ lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
memcpy(&key.addr, addr, addrlen);
key.addrlen = addrlen;
key.outnet = outnet;
+ key.opt_list = opt_list;
return (struct serviced_query*)rbtree_search(outnet->serviced, &key);
}
@@ -1237,7 +1297,7 @@ static struct serviced_query*
serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, int qtype)
+ size_t zonelen, int qtype, struct edns_option* opt_list)
{
struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
#ifdef UNBOUND_DEBUG
@@ -1267,6 +1327,16 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
sq->ssl_upstream = ssl_upstream;
memcpy(&sq->addr, addr, addrlen);
sq->addrlen = addrlen;
+ sq->opt_list = NULL;
+ if(opt_list) {
+ sq->opt_list = edns_opt_copy_alloc(opt_list);
+ if(!sq->opt_list) {
+ free(sq->zone);
+ free(sq->qbuf);
+ free(sq);
+ return NULL;
+ }
+ }
sq->outnet = outnet;
sq->cblist = NULL;
sq->pending = NULL;
@@ -1346,6 +1416,7 @@ serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len)
long int random = 0;
int bits = 0;
log_assert(len >= 10 + 5 /* offset qname, root, qtype, qclass */);
+ (void)len;
lablen = *d++;
while(lablen) {
while(lablen--) {
@@ -1394,6 +1465,7 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
edns.edns_present = 1;
edns.ext_rcode = 0;
edns.edns_version = EDNS_ADVERTISED_VERSION;
+ edns.opt_list = sq->opt_list;
if(sq->status == serviced_query_UDP_EDNS_FRAG) {
if(addr_is_ip6(&sq->addr, sq->addrlen)) {
if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
@@ -1527,7 +1599,10 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
sq->to_be_deleted = 1;
verbose(VERB_ALGO, "svcd callbacks start");
if(sq->outnet->use_caps_for_id && error == NETEVENT_NOERROR && c &&
- !sq->nocaps) {
+ !sq->nocaps && sq->qtype != LDNS_RR_TYPE_PTR) {
+ /* for type PTR do not check perturbed name in answer,
+ * compatibility with cisco dns guard boxes that mess up
+ * reverse queries 0x20 contents */
/* noerror and nxdomain must have a qname in reply */
if(sldns_buffer_read_u16_at(c->buffer, 4) == 0 &&
(LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer))
@@ -1708,6 +1783,44 @@ serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff)
return sq->pending != NULL;
}
+/* see if packet is edns malformed; got zeroes at start.
+ * This is from servers that return malformed packets to EDNS0 queries,
+ * but they return good packets for nonEDNS0 queries.
+ * We try to detect their output; without resorting to a full parse or
+ * check for too many bytes after the end of the packet. */
+static int
+packet_edns_malformed(struct sldns_buffer* buf, int qtype)
+{
+ size_t len;
+ if(sldns_buffer_limit(buf) < LDNS_HEADER_SIZE)
+ return 1; /* malformed */
+ /* they have NOERROR rcode, 1 answer. */
+ if(LDNS_RCODE_WIRE(sldns_buffer_begin(buf)) != LDNS_RCODE_NOERROR)
+ return 0;
+ /* one query (to skip) and answer records */
+ if(LDNS_QDCOUNT(sldns_buffer_begin(buf)) != 1 ||
+ LDNS_ANCOUNT(sldns_buffer_begin(buf)) == 0)
+ return 0;
+ /* skip qname */
+ len = dname_valid(sldns_buffer_at(buf, LDNS_HEADER_SIZE),
+ sldns_buffer_limit(buf)-LDNS_HEADER_SIZE);
+ if(len == 0)
+ return 0;
+ if(len == 1 && qtype == 0)
+ return 0; /* we asked for '.' and type 0 */
+ /* and then 4 bytes (type and class of query) */
+ if(sldns_buffer_limit(buf) < LDNS_HEADER_SIZE + len + 4 + 3)
+ return 0;
+
+ /* and start with 11 zeroes as the answer RR */
+ /* so check the qtype of the answer record, qname=0, type=0 */
+ if(sldns_buffer_at(buf, LDNS_HEADER_SIZE+len+4)[0] == 0 &&
+ sldns_buffer_at(buf, LDNS_HEADER_SIZE+len+4)[1] == 0 &&
+ sldns_buffer_at(buf, LDNS_HEADER_SIZE+len+4)[2] == 0)
+ return 1;
+ return 0;
+}
+
int
serviced_udp_callback(struct comm_point* c, void* arg, int error,
struct comm_reply* rep)
@@ -1778,7 +1891,9 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
||sq->status == serviced_query_UDP_EDNS_FRAG)
&& (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer))
== LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(
- sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL)) {
+ sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL
+ || packet_edns_malformed(c->buffer, sq->qtype)
+ )) {
/* try to get an answer by falling back without EDNS */
verbose(VERB_ALGO, "serviced query: attempt without EDNS");
sq->status = serviced_query_UDP_EDNS_fallback;
@@ -1873,15 +1988,15 @@ struct serviced_query*
outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
- int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* zone, size_t zonelen,
- comm_point_callback_t* callback, void* callback_arg,
+ int tcp_upstream, int ssl_upstream, struct edns_option* opt_list,
+ struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
+ size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
sldns_buffer* buff)
{
struct serviced_query* sq;
struct service_callback* cb;
serviced_gen_query(buff, qname, qnamelen, qtype, qclass, flags);
- sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen);
+ sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen, opt_list);
/* duplicate entries are included in the callback list, because
* there is a counterpart registration by our caller that needs to
* be doubly-removed (with callbacks perhaps). */
@@ -1891,7 +2006,7 @@ outnet_serviced_query(struct outside_network* outnet,
/* make new serviced query entry */
sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
tcp_upstream, ssl_upstream, addr, addrlen, zone,
- zonelen, (int)qtype);
+ zonelen, (int)qtype, opt_list);
if(!sq) {
free(cb);
return NULL;
@@ -1948,13 +2063,7 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
callback_list_remove(sq, cb_arg);
/* if callbacks() routine scheduled deletion, let it do that */
if(!sq->cblist && !sq->to_be_deleted) {
-#ifdef UNBOUND_DEBUG
- rbnode_t* rem =
-#else
- (void)
-#endif
- rbtree_delete(sq->outnet->serviced, sq);
- log_assert(rem); /* should be present */
+ (void)rbtree_delete(sq->outnet->serviced, sq);
serviced_delete(sq);
}
}
diff --git a/contrib/unbound/services/outside_network.h b/contrib/unbound/services/outside_network.h
index 36f798d..d6a448c 100644
--- a/contrib/unbound/services/outside_network.h
+++ b/contrib/unbound/services/outside_network.h
@@ -58,6 +58,7 @@ struct port_if;
struct sldns_buffer;
struct serviced_query;
struct dt_env;
+struct edns_option;
/**
* Send queries to outside servers and wait for answers from servers.
@@ -164,6 +165,10 @@ struct port_if {
/** length of addr field */
socklen_t addrlen;
+ /** prefix length of network address (in bits), for randomisation.
+ * if 0, no randomisation. */
+ int pfxlen;
+
/** the available ports array. These are unused.
* Only the first total-inuse part is filled. */
int* avail_ports;
@@ -367,6 +372,8 @@ struct serviced_query {
int last_rtt;
/** do we know edns probe status already, for UDP_EDNS queries */
int edns_lame_known;
+ /** edns options to use for sending upstream packet */
+ struct edns_option* opt_list;
/** outside network this is part of */
struct outside_network* outnet;
/** list of interested parties that need callback on results. */
@@ -477,6 +484,8 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
* @param nocaps: ignore use_caps_for_id and use unperturbed qname.
* @param tcp_upstream: use TCP for upstream queries.
* @param ssl_upstream: use SSL for upstream queries.
+ * @param opt_list: pass edns option list (deep copied into serviced query)
+ * these options are set on the outgoing packets.
* @param callback: callback function.
* @param callback_arg: user argument to callback function.
* @param addr: to which server to send the query.
@@ -492,9 +501,9 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
- int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* zone, size_t zonelen,
- comm_point_callback_t* callback, void* callback_arg,
+ int tcp_upstream, int ssl_upstream, struct edns_option* opt_list,
+ struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
+ size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
struct sldns_buffer* buff);
/**
diff --git a/contrib/unbound/sldns/keyraw.c b/contrib/unbound/sldns/keyraw.c
index 59e8000..e8f2da0 100644
--- a/contrib/unbound/sldns/keyraw.c
+++ b/contrib/unbound/sldns/keyraw.c
@@ -23,6 +23,15 @@
#ifdef HAVE_OPENSSL_ENGINE_H
# include <openssl/engine.h>
#endif
+#ifdef HAVE_OPENSSL_BN_H
+#include <openssl/bn.h>
+#endif
+#ifdef HAVE_OPENSSL_RSA_H
+#include <openssl/rsa.h>
+#endif
+#ifdef HAVE_OPENSSL_DSA_H
+#include <openssl/dsa.h>
+#endif
#endif /* HAVE_SSL */
size_t
@@ -206,7 +215,6 @@ sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
offset += length;
Y = BN_bin2bn(key+offset, (int)length, NULL);
- offset += length;
/* create the key and set its properties */
if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
@@ -216,6 +224,7 @@ sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
BN_free(Y);
return NULL;
}
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
#ifndef S_SPLINT_S
dsa->p = P;
dsa->q = Q;
@@ -223,6 +232,25 @@ sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
dsa->pub_key = Y;
#endif /* splint */
+#else /* OPENSSL_VERSION_NUMBER */
+ if (!DSA_set0_pqg(dsa, P, Q, G)) {
+ /* QPG not yet attached, need to free */
+ BN_free(Q);
+ BN_free(P);
+ BN_free(G);
+
+ DSA_free(dsa);
+ BN_free(Y);
+ return NULL;
+ }
+ if (!DSA_set0_key(dsa, Y, NULL)) {
+ /* QPG attached, cleaned up by DSA_fre() */
+ DSA_free(dsa);
+ BN_free(Y);
+ return NULL;
+ }
+#endif
+
return dsa;
}
@@ -274,11 +302,21 @@ sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
BN_free(modulus);
return NULL;
}
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
#ifndef S_SPLINT_S
rsa->n = modulus;
rsa->e = exponent;
#endif /* splint */
+#else /* OPENSSL_VERSION_NUMBER */
+ if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
+ BN_free(exponent);
+ BN_free(modulus);
+ RSA_free(rsa);
+ return NULL;
+ }
+#endif
+
return rsa;
}
diff --git a/contrib/unbound/sldns/parseutil.c b/contrib/unbound/sldns/parseutil.c
index 2a2ebbb..3271761 100644
--- a/contrib/unbound/sldns/parseutil.c
+++ b/contrib/unbound/sldns/parseutil.c
@@ -637,7 +637,7 @@ int sldns_b64_ntop(uint8_t const *src, size_t srclength,
target[o+1] = b64[ ((src[i]&0x03)<<4) | (src[i+1]>>4) ];
target[o+2] = b64[ ((src[i+1]&0x0f)<<2) ];
target[o+3] = pad64;
- i += 2;
+ /* i += 2; */
o += 4;
break;
case 1:
@@ -646,7 +646,7 @@ int sldns_b64_ntop(uint8_t const *src, size_t srclength,
target[o+1] = b64[ ((src[i]&0x03)<<4) ];
target[o+2] = pad64;
target[o+3] = pad64;
- i += 1;
+ /* i += 1; */
o += 4;
break;
case 0:
diff --git a/contrib/unbound/sldns/rrdef.h b/contrib/unbound/sldns/rrdef.h
index d9302ec..00c01e6 100644
--- a/contrib/unbound/sldns/rrdef.h
+++ b/contrib/unbound/sldns/rrdef.h
@@ -195,7 +195,7 @@ enum sldns_enum_rr_type
LDNS_RR_TYPE_TALINK = 58,
LDNS_RR_TYPE_CDS = 59, /** RFC 7344 */
LDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */
- LDNS_RR_TYPE_OPENPGPKEY = 61, /* draft-ietf-dane-openpgpkey */
+ LDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */
LDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */
LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */
@@ -420,7 +420,8 @@ enum sldns_enum_edns_option
LDNS_EDNS_DAU = 5, /* RFC6975 */
LDNS_EDNS_DHU = 6, /* RFC6975 */
LDNS_EDNS_N3U = 7, /* RFC6975 */
- LDNS_EDNS_CLIENT_SUBNET = 8 /* draft-vandergaast-edns-client-subnet */
+ LDNS_EDNS_CLIENT_SUBNET = 8, /* draft-vandergaast-edns-client-subnet */
+ LDNS_EDNS_PADDING = 12 /* RFC7830 */
};
typedef enum sldns_enum_edns_option sldns_edns_option;
diff --git a/contrib/unbound/sldns/str2wire.c b/contrib/unbound/sldns/str2wire.c
index c541083..e624e26 100644
--- a/contrib/unbound/sldns/str2wire.c
+++ b/contrib/unbound/sldns/str2wire.c
@@ -892,10 +892,10 @@ int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
parse_state?parse_state->default_ttl:0,
(parse_state&&parse_state->origin_len)?
parse_state->origin:NULL,
- parse_state->origin_len,
+ parse_state?parse_state->origin_len:0,
(parse_state&&parse_state->prev_rr_len)?
parse_state->prev_rr:NULL,
- parse_state->prev_rr_len);
+ parse_state?parse_state->prev_rr_len:0);
}
return LDNS_WIREPARSE_ERR_OK;
}
diff --git a/contrib/unbound/sldns/wire2str.c b/contrib/unbound/sldns/wire2str.c
index 5cbd78e..639f56f 100644
--- a/contrib/unbound/sldns/wire2str.c
+++ b/contrib/unbound/sldns/wire2str.c
@@ -165,6 +165,7 @@ static sldns_lookup_table sldns_edns_options_data[] = {
{ 6, "DHU" },
{ 7, "N3U" },
{ 8, "edns-client-subnet" },
+ { 12, "Padding" },
{ 0, NULL}
};
sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;
@@ -1864,6 +1865,9 @@ int sldns_wire2str_edns_option_print(char** s, size_t* sl,
case LDNS_EDNS_CLIENT_SUBNET:
w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen);
break;
+ case LDNS_EDNS_PADDING:
+ w += print_hex_buf(s, sl, optdata, optlen);
+ break;
default:
/* unknown option code */
w += print_hex_buf(s, sl, optdata, optlen);
diff --git a/contrib/unbound/sldns/wire2str.h b/contrib/unbound/sldns/wire2str.h
index 67f5435..c477f06 100644
--- a/contrib/unbound/sldns/wire2str.h
+++ b/contrib/unbound/sldns/wire2str.h
@@ -118,7 +118,7 @@ int sldns_str_print(char** str, size_t* slen, const char* format, ...)
* @param str_len: the size of the string buffer. If more is needed, it'll
* silently truncate the output to fit in the buffer.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_pkt_buf(uint8_t* data, size_t data_len, char* str,
size_t str_len);
@@ -351,7 +351,7 @@ int sldns_wire2str_edns_option_code_print(char** str, size_t* str_len,
* @param str_len: the size of the string buffer. If more is needed, it'll
* silently truncate the output to fit in the buffer.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str,
size_t str_len);
@@ -369,7 +369,7 @@ int sldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str,
* @param str_len: the size of the string buffer. If more is needed, it'll
* silently truncate the output to fit in the buffer.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_rr_unknown_buf(uint8_t* rr, size_t rr_len, char* str,
size_t str_len);
@@ -389,7 +389,7 @@ int sldns_wire2str_rr_unknown_buf(uint8_t* rr, size_t rr_len, char* str,
* @param str_len: the size of the string buffer. If more is needed, it'll
* silently truncate the output to fit in the buffer.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rr_len, size_t dname_len,
char* str, size_t str_len);
@@ -406,7 +406,7 @@ int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rr_len, size_t dname_len,
* silently truncate the output to fit in the buffer.
* @param rrtype: rr type of the data
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
size_t str_len, uint16_t rrtype);
@@ -417,7 +417,7 @@ int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
* @param str: the string to write to.
* @param len: length of str.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_type_buf(uint16_t rrtype, char* str, size_t len);
@@ -427,7 +427,7 @@ int sldns_wire2str_type_buf(uint16_t rrtype, char* str, size_t len);
* @param str: the string to write to.
* @param len: length of str.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len);
@@ -437,7 +437,7 @@ int sldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len);
* @param str: the string to write to.
* @param len: length of str.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_rcode_buf(int rcode, char* str, size_t len);
@@ -448,7 +448,7 @@ int sldns_wire2str_rcode_buf(int rcode, char* str, size_t len);
* @param str: the string to write to.
* @param len: length of string.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_dname_buf(uint8_t* dname, size_t dname_len, char* str,
size_t len);
diff --git a/contrib/unbound/smallapp/unbound-anchor.c b/contrib/unbound/smallapp/unbound-anchor.c
index 81bb896..68e8e40 100644
--- a/contrib/unbound/smallapp/unbound-anchor.c
+++ b/contrib/unbound/smallapp/unbound-anchor.c
@@ -37,7 +37,8 @@
* \file
*
* This file checks to see that the current 5011 keys work to prime the
- * current root anchor. If not a certificate is used to update the anchor.
+ * current root anchor. If not a certificate is used to update the anchor,
+ * with RFC7958 https xml fetch.
*
* This is a concept solution for distribution of the DNSSEC root
* trust anchor. It is a small tool, called "unbound-anchor", that
@@ -47,7 +48,7 @@
* Management-Abstract:
* * first run: fill root.key file with hardcoded DS record.
* * mostly: use RFC5011 tracking, quick . DNSKEY UDP query.
- * * failover: use builtin certificate, do https and update.
+ * * failover: use RFC7958 builtin certificate, do https and update.
* Special considerations:
* * 30-days RFC5011 timer saves a lot of https traffic.
* * DNSKEY probe must be NOERROR, saves a lot of https traffic.
@@ -77,7 +78,7 @@
* the file contains a list of normal DNSKEY/DS records, and uses that to
* bootstrap 5011 (the KSK is made VALID).
*
- * The certificate update is done by fetching root-anchors.xml and
+ * The certificate RFC7958 update is done by fetching root-anchors.xml and
* root-anchors.p7s via SSL. The HTTPS certificate can be logged but is
* not validated (https for channel security; the security comes from the
* certificate). The 'data.iana.org' domain name A and AAAA are resolved
@@ -171,7 +172,7 @@ struct ip_list {
/** Give unbound-anchor usage, and exit (1). */
static void
-usage()
+usage(void)
{
printf("Usage: unbound-anchor [opts]\n");
printf(" Setup or update root anchor. "
@@ -419,7 +420,7 @@ read_builtin_cert(void)
{
const char* builtin_cert = get_builtin_cert();
STACK_OF(X509)* sk;
- BIO *bio = BIO_new_mem_buf((void*)builtin_cert,
+ BIO *bio = BIO_new_mem_buf(builtin_cert,
(int)strlen(builtin_cert));
if(!bio) {
if(verb) printf("out of memory\n");
@@ -1836,7 +1837,7 @@ write_unsigned_root(const char* root_anchor_file)
#ifdef HAVE_FSYNC
fsync(fileno(out));
#else
- FlushFileBuffers((HANDLE)_fileno(out));
+ FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
#endif
fclose(out);
}
@@ -1868,7 +1869,7 @@ write_root_anchor(const char* root_anchor_file, BIO* ds)
#ifdef HAVE_FSYNC
fsync(fileno(out));
#else
- FlushFileBuffers((HANDLE)_fileno(out));
+ FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
#endif
fclose(out);
}
@@ -2310,10 +2311,22 @@ int main(int argc, char* argv[])
if(argc != 0)
usage();
+#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
ERR_load_crypto_strings();
+#endif
ERR_load_SSL_strings();
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
OpenSSL_add_all_algorithms();
+#else
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
+#else
+ (void)OPENSSL_init_ssl(0, NULL);
+#endif
if(dolist) do_list_builtin();
diff --git a/contrib/unbound/smallapp/unbound-checkconf.c b/contrib/unbound/smallapp/unbound-checkconf.c
index ec07713..51f8e64 100644
--- a/contrib/unbound/smallapp/unbound-checkconf.c
+++ b/contrib/unbound/smallapp/unbound-checkconf.c
@@ -72,7 +72,7 @@
/** Give checkconf usage, and exit (1). */
static void
-usage()
+usage(void)
{
printf("Usage: unbound-checkconf [file]\n");
printf(" Checks unbound configuration file for errors.\n");
@@ -161,6 +161,7 @@ warn_hosts(const char* typ, struct config_stub* list)
static void
interfacechecks(struct config_file* cfg)
{
+ int d;
struct sockaddr_storage a;
socklen_t alen;
int i, j;
@@ -177,8 +178,8 @@ interfacechecks(struct config_file* cfg)
}
}
for(i=0; i<cfg->num_out_ifs; i++) {
- if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT,
- &a, &alen)) {
+ if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen) &&
+ !netblockstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen, &d)) {
fatal_exit("cannot parse outgoing-interface "
"specified as '%s'", cfg->out_ifs[i]);
}
@@ -330,6 +331,8 @@ morechecks(struct config_file* cfg, const char* fname)
fatal_exit("num_threads value weird");
if(!cfg->do_ip4 && !cfg->do_ip6)
fatal_exit("ip4 and ip6 are both disabled, pointless");
+ if(!cfg->do_ip6 && cfg->prefer_ip6)
+ fatal_exit("cannot prefer and disable ip6, pointless");
if(!cfg->do_udp && !cfg->do_tcp)
fatal_exit("udp and tcp are both disabled, pointless");
if(cfg->edns_buffer_size > cfg->msg_buffer_size)
@@ -412,6 +415,21 @@ morechecks(struct config_file* cfg, const char* fname)
&& strcmp(cfg->module_conf, "python dns64 iterator") != 0
&& strcmp(cfg->module_conf, "python dns64 validator iterator") != 0
#endif
+#ifdef USE_CACHEDB
+ && strcmp(cfg->module_conf, "validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "python dns64 cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "python dns64 validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 python cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 python validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "python cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "python validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "cachedb python iterator") != 0
+ && strcmp(cfg->module_conf, "validator cachedb python iterator") != 0
+ && strcmp(cfg->module_conf, "validator python cachedb iterator") != 0
+#endif
) {
fatal_exit("module conf '%s' is not known to work",
cfg->module_conf);
@@ -421,7 +439,9 @@ morechecks(struct config_file* cfg, const char* fname)
if(cfg->username && cfg->username[0]) {
if(getpwnam(cfg->username) == NULL)
fatal_exit("user '%s' does not exist.", cfg->username);
+# ifdef HAVE_ENDPWENT
endpwent();
+# endif
}
#endif
if(cfg->remote_control_enable && cfg->remote_control_use_cert) {
@@ -466,14 +486,22 @@ check_hints(struct config_file* cfg)
static void
checkconf(const char* cfgfile, const char* opt, int final)
{
+ char oldwd[PATH_MAX];
struct config_file* cfg = config_create();
if(!cfg)
fatal_exit("out of memory");
+ oldwd[0] = 0;
+ if(!getcwd(oldwd, sizeof(oldwd))) {
+ log_err("cannot getcwd: %s", strerror(errno));
+ oldwd[0] = 0;
+ }
if(!config_read(cfg, cfgfile, NULL)) {
/* config_read prints messages to stderr */
config_delete(cfg);
exit(1);
}
+ if(oldwd[0] && chdir(oldwd) == -1)
+ log_err("cannot chdir(%s): %s", oldwd, strerror(errno));
if(opt) {
print_option(cfg, opt, final);
config_delete(cfg);
diff --git a/contrib/unbound/smallapp/unbound-control.c b/contrib/unbound/smallapp/unbound-control.c
index fac73b0..19268ed 100644
--- a/contrib/unbound/smallapp/unbound-control.c
+++ b/contrib/unbound/smallapp/unbound-control.c
@@ -65,7 +65,7 @@
/** Give unbound-control usage, and exit (1). */
static void
-usage()
+usage(void)
{
printf("Usage: unbound-control [options] command\n");
printf(" Remote control utility for unbound server.\n");
@@ -102,7 +102,7 @@ usage()
printf(" flush_negative flush all negative data\n");
printf(" flush_stats flush statistics, make zero\n");
printf(" flush_requestlist drop queries that are worked on\n");
- printf(" dump_requestlist show what is worked on\n");
+ printf(" dump_requestlist show what is worked on by first thread\n");
printf(" flush_infra [all | ip] remove ping, edns for one IP or all\n");
printf(" dump_infra show ping and edns entries\n");
printf(" set_option opt: val set option to value, no reload\n");
@@ -212,7 +212,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
struct sockaddr_un* usock = (struct sockaddr_un *) &addr;
usock->sun_family = AF_LOCAL;
#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
- usock->sun_len = (socklen_t)sizeof(usock);
+ usock->sun_len = (unsigned)sizeof(usock);
#endif
(void)strlcpy(usock->sun_path, svr, sizeof(usock->sun_path));
addrlen = (socklen_t)sizeof(struct sockaddr_un);
@@ -418,10 +418,22 @@ int main(int argc, char* argv[])
cfgfile = CONFIGFILE;
#endif
+#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
ERR_load_crypto_strings();
+#endif
ERR_load_SSL_strings();
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
OpenSSL_add_all_algorithms();
+#else
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
+#else
+ (void)OPENSSL_init_ssl(0, NULL);
+#endif
if(!RAND_status()) {
/* try to seed it */
diff --git a/contrib/unbound/smallapp/unbound-host.c b/contrib/unbound/smallapp/unbound-host.c
index 30fef51..d7a36a2 100644
--- a/contrib/unbound/smallapp/unbound-host.c
+++ b/contrib/unbound/smallapp/unbound-host.c
@@ -72,7 +72,7 @@ static int verb = 0;
/** Give unbound-host usage, and exit (1). */
static void
-usage()
+usage(void)
{
printf("Usage: unbound-host [-vdhr46] [-c class] [-t type] hostname\n");
printf(" [-y key] [-f keyfile] [-F namedkeyfile]\n");
@@ -91,7 +91,7 @@ usage()
printf(" -F keyfile read named.conf-style trust anchors.\n");
printf(" -C config use the specified unbound.conf (none read by default)\n");
printf(" -r read forwarder information from /etc/resolv.conf\n");
- printf(" breaks validation if the fwder does not do DNSSEC.\n");
+ printf(" breaks validation if the forwarder does not do DNSSEC.\n");
printf(" -v be more verbose, shows nodata and security.\n");
printf(" -d debug, traces the action, -d -d shows more.\n");
printf(" -4 use ipv4 network, avoid ipv6.\n");
diff --git a/contrib/unbound/smallapp/worker_cb.c b/contrib/unbound/smallapp/worker_cb.c
index 8193bec..fd8488a 100644
--- a/contrib/unbound/smallapp/worker_cb.c
+++ b/contrib/unbound/smallapp/worker_cb.c
@@ -103,7 +103,8 @@ struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
+ struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{
@@ -135,7 +136,8 @@ struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
+ struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{
@@ -223,8 +225,8 @@ struct order_id {
int order_lock_cmp(const void* e1, const void* e2)
{
- struct order_id* o1 = (struct order_id*)e1;
- struct order_id* o2 = (struct order_id*)e2;
+ const struct order_id* o1 = e1;
+ const struct order_id* o2 = e2;
if(o1->thr < o2->thr) return -1;
if(o1->thr > o2->thr) return 1;
if(o1->instance < o2->instance) return -1;
@@ -235,7 +237,7 @@ int order_lock_cmp(const void* e1, const void* e2)
int
codeline_cmp(const void* a, const void* b)
{
- return strcmp((const char*)a, (const char*)b);
+ return strcmp(a, b);
}
int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
diff --git a/contrib/unbound/util/alloc.c b/contrib/unbound/util/alloc.c
index 05d2fa3..a1152a7 100644
--- a/contrib/unbound/util/alloc.c
+++ b/contrib/unbound/util/alloc.c
@@ -64,7 +64,7 @@ alloc_setup_special(alloc_special_t* t)
* @param alloc: the structure to fill up.
*/
static void
-prealloc(struct alloc_cache* alloc)
+prealloc_setup(struct alloc_cache* alloc)
{
alloc_special_t* p;
int i;
@@ -216,7 +216,7 @@ alloc_special_obtain(struct alloc_cache* alloc)
}
}
/* allocate new */
- prealloc(alloc);
+ prealloc_setup(alloc);
if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t)))) {
log_err("alloc_special_obtain: out of memory");
return NULL;
diff --git a/contrib/unbound/util/config_file.c b/contrib/unbound/util/config_file.c
index 420dc71..688211c 100644
--- a/contrib/unbound/util/config_file.c
+++ b/contrib/unbound/util/config_file.c
@@ -163,6 +163,7 @@ config_create(void)
cfg->so_sndbuf = 0;
cfg->so_reuseport = 0;
cfg->ip_transparent = 0;
+ cfg->ip_freebind = 0;
cfg->num_ifs = 0;
cfg->ifs = NULL;
cfg->num_out_ifs = 0;
@@ -211,6 +212,7 @@ config_create(void)
cfg->local_zones = NULL;
cfg->local_zones_nodefault = NULL;
cfg->local_data = NULL;
+ cfg->local_zone_overrides = NULL;
cfg->unblock_lan_zones = 0;
cfg->insecure_lan_zones = 0;
cfg->python_script = NULL;
@@ -237,6 +239,7 @@ config_create(void)
if(!(cfg->dnstap_socket_path = strdup(DNSTAP_SOCKET_PATH)))
goto error_exit;
#endif
+ cfg->disable_dnssec_lame_check = 0;
cfg->ratelimit = 0;
cfg->ratelimit_slabs = 4;
cfg->ratelimit_size = 4*1024*1024;
@@ -393,6 +396,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_MEMSIZE("so-sndbuf:", so_sndbuf)
else S_YNO("so-reuseport:", so_reuseport)
else S_YNO("ip-transparent:", ip_transparent)
+ else S_YNO("ip-freebind:", ip_freebind)
else S_MEMSIZE("rrset-cache-size:", rrset_cache_size)
else S_POW2("rrset-cache-slabs:", rrset_cache_slabs)
else S_YNO("prefetch:", prefetch)
@@ -473,6 +477,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("control-cert-file:", control_cert_file)
else S_STR("module-config:", module_conf)
else S_STR("python-script:", python_script)
+ else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
else if(strcmp(opt, "ratelimit:") == 0) {
IS_NUMBER_OR_ZERO; cfg->ratelimit = atoi(val);
infra_dp_ratelimit=cfg->ratelimit;
@@ -481,9 +486,11 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_POW2("ratelimit-slabs:", ratelimit_slabs)
else S_NUMBER_OR_ZERO("ratelimit-factor:", ratelimit_factor)
else S_YNO("qname-minimisation:", qname_minimisation)
+ else if(strcmp(opt, "define-tag:") ==0) {
+ return config_add_tag(cfg, val);
/* val_sig_skew_min and max are copied into val_env during init,
* so this does not update val_env with set_option */
- else if(strcmp(opt, "val-sig-skew-min:") == 0)
+ } else if(strcmp(opt, "val-sig-skew-min:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->val_sig_skew_min = (int32_t)atoi(val); }
else if(strcmp(opt, "val-sig-skew-max:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->val_sig_skew_max = (int32_t)atoi(val); }
@@ -504,7 +511,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
* stub-zone, name, stub-addr, stub-host, stub-prime
* forward-first, stub-first,
* forward-zone, name, forward-addr, forward-host,
- * ratelimit-for-domain, ratelimit-below-domain */
+ * ratelimit-for-domain, ratelimit-below-domain,
+ * local-zone-tag */
return 0;
}
return 1;
@@ -628,9 +636,31 @@ config_collate_cat(struct config_strlist* list)
/** compare and print list option */
#define O_LS2(opt, name, lst) if(strcmp(opt, name)==0) { \
struct config_str2list* p = cfg->lst; \
- for(p = cfg->lst; p; p = p->next) \
- snprintf(buf, len, "%s %s\n", p->str, p->str2); \
+ for(p = cfg->lst; p; p = p->next) { \
+ snprintf(buf, len, "%s %s", p->str, p->str2); \
+ func(buf, arg); \
+ } \
+ }
+/** compare and print list option */
+#define O_LS3(opt, name, lst) if(strcmp(opt, name)==0) { \
+ struct config_str3list* p = cfg->lst; \
+ for(p = cfg->lst; p; p = p->next) { \
+ snprintf(buf, len, "%s %s %s", p->str, p->str2, p->str3); \
func(buf, arg); \
+ } \
+ }
+/** compare and print taglist option */
+#define O_LTG(opt, name, lst) if(strcmp(opt, name)==0) { \
+ char* tmpstr = NULL; \
+ struct config_strbytelist *p = cfg->lst; \
+ for(p = cfg->lst; p; p = p->next) {\
+ tmpstr = config_taglist2str(cfg, p->str2, p->str2len); \
+ if(tmpstr) {\
+ snprintf(buf, len, "%s %s", p->str, tmpstr); \
+ func(buf, arg); \
+ free(tmpstr); \
+ } \
+ } \
}
int
@@ -664,6 +694,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_MEM(opt, "so-sndbuf", so_sndbuf)
else O_YNO(opt, "so-reuseport", so_reuseport)
else O_YNO(opt, "ip-transparent", ip_transparent)
+ else O_YNO(opt, "ip-freebind", ip_freebind)
else O_MEM(opt, "rrset-cache-size", rrset_cache_size)
else O_DEC(opt, "rrset-cache-slabs", rrset_cache_slabs)
else O_YNO(opt, "prefetch-key", prefetch_key)
@@ -750,6 +781,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
else O_DEC(opt, "max-udp-size", max_udp_size)
else O_STR(opt, "python-script", python_script)
+ else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
else O_DEC(opt, "ratelimit", ratelimit)
else O_MEM(opt, "ratelimit-size", ratelimit_size)
else O_DEC(opt, "ratelimit-slabs", ratelimit_slabs)
@@ -759,6 +791,12 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min)
else O_DEC(opt, "val-sig-skew-max", val_sig_skew_max)
else O_YNO(opt, "qname-minimisation", qname_minimisation)
+ else O_IFC(opt, "define-tag", num_tags, tagname)
+ else O_LTG(opt, "local-zone-tag", local_zone_tags)
+ else O_LTG(opt, "access-control-tag", acl_tags)
+ else O_LS3(opt, "local-zone-override", local_zone_overrides)
+ else O_LS3(opt, "access-control-tag-action", acl_tag_actions)
+ else O_LS3(opt, "access-control-tag-data", acl_tag_datas)
/* not here:
* outgoing-permit, outgoing-avoid - have list of ports
* local-zone - zones and nodefault variables
@@ -911,6 +949,20 @@ config_deldblstrlist(struct config_str2list* p)
}
void
+config_deltrplstrlist(struct config_str3list* p)
+{
+ struct config_str3list *np;
+ while(p) {
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p->str3);
+ free(p);
+ p = np;
+ }
+}
+
+void
config_delstub(struct config_stub* p)
{
if(!p) return;
@@ -931,6 +983,32 @@ config_delstubs(struct config_stub* p)
}
}
+/** delete string array */
+static void
+config_del_strarray(char** array, int num)
+{
+ int i;
+ if(!array)
+ return;
+ for(i=0; i<num; i++) {
+ free(array[i]);
+ }
+ free(array);
+}
+
+void
+config_del_strbytelist(struct config_strbytelist* p)
+{
+ struct config_strbytelist* np;
+ while(p) {
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p);
+ p = np;
+ }
+}
+
void
config_delete(struct config_file* cfg)
{
@@ -943,18 +1021,8 @@ config_delete(struct config_file* cfg)
free(cfg->target_fetch_policy);
free(cfg->ssl_service_key);
free(cfg->ssl_service_pem);
- if(cfg->ifs) {
- int i;
- for(i=0; i<cfg->num_ifs; i++)
- free(cfg->ifs[i]);
- free(cfg->ifs);
- }
- if(cfg->out_ifs) {
- int i;
- for(i=0; i<cfg->num_out_ifs; i++)
- free(cfg->out_ifs[i]);
- free(cfg->out_ifs);
- }
+ config_del_strarray(cfg->ifs, cfg->num_ifs);
+ config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
config_delstubs(cfg->stubs);
config_delstubs(cfg->forwards);
config_delstrlist(cfg->donotqueryaddrs);
@@ -978,6 +1046,12 @@ config_delete(struct config_file* cfg)
config_deldblstrlist(cfg->local_zones);
config_delstrlist(cfg->local_zones_nodefault);
config_delstrlist(cfg->local_data);
+ config_deltrplstrlist(cfg->local_zone_overrides);
+ config_del_strarray(cfg->tagname, cfg->num_tags);
+ config_del_strbytelist(cfg->local_zone_tags);
+ config_del_strbytelist(cfg->acl_tags);
+ config_deltrplstrlist(cfg->acl_tag_actions);
+ config_deltrplstrlist(cfg->acl_tag_datas);
config_delstrlist(cfg->control_ifs);
free(cfg->server_key_file);
free(cfg->server_cert_file);
@@ -1136,6 +1210,23 @@ int cfg_strlist_append(struct config_strlist_head* list, char* item)
}
int
+cfg_region_strlist_insert(struct regional* region,
+ struct config_strlist** head, char* item)
+{
+ struct config_strlist *s;
+ if(!item || !head)
+ return 0;
+ s = (struct config_strlist*)regional_alloc_zero(region,
+ sizeof(struct config_strlist));
+ if(!s)
+ return 0;
+ s->str = item;
+ s->next = *head;
+ *head = s;
+ return 1;
+}
+
+int
cfg_strlist_insert(struct config_strlist** head, char* item)
{
struct config_strlist *s;
@@ -1166,6 +1257,42 @@ cfg_str2list_insert(struct config_str2list** head, char* item, char* i2)
return 1;
}
+int
+cfg_str3list_insert(struct config_str3list** head, char* item, char* i2,
+ char* i3)
+{
+ struct config_str3list *s;
+ if(!item || !i2 || !i3 || !head)
+ return 0;
+ s = (struct config_str3list*)calloc(1, sizeof(struct config_str3list));
+ if(!s)
+ return 0;
+ s->str = item;
+ s->str2 = i2;
+ s->str3 = i3;
+ s->next = *head;
+ *head = s;
+ return 1;
+}
+
+int
+cfg_strbytelist_insert(struct config_strbytelist** head, char* item,
+ uint8_t* i2, size_t i2len)
+{
+ struct config_strbytelist* s;
+ if(!item || !i2 || !head)
+ return 0;
+ s = (struct config_strbytelist*)calloc(1, sizeof(*s));
+ if(!s)
+ return 0;
+ s->str = item;
+ s->str2 = i2;
+ s->str2len = i2len;
+ s->next = *head;
+ *head = s;
+ return 1;
+}
+
time_t
cfg_convert_timeval(const char* str)
{
@@ -1270,6 +1397,123 @@ cfg_parse_memsize(const char* str, size_t* res)
return 1;
}
+int
+find_tag_id(struct config_file* cfg, const char* tag)
+{
+ int i;
+ for(i=0; i<cfg->num_tags; i++) {
+ if(strcmp(cfg->tagname[i], tag) == 0)
+ return i;
+ }
+ return -1;
+}
+
+int
+config_add_tag(struct config_file* cfg, const char* tag)
+{
+ char** newarray;
+ char* newtag;
+ if(find_tag_id(cfg, tag) != -1)
+ return 1; /* nothing to do */
+ newarray = (char**)malloc(sizeof(char*)*(cfg->num_tags+1));
+ if(!newarray)
+ return 0;
+ newtag = strdup(tag);
+ if(!newtag) {
+ free(newarray);
+ return 0;
+ }
+ if(cfg->tagname) {
+ memcpy(newarray, cfg->tagname, sizeof(char*)*cfg->num_tags);
+ free(cfg->tagname);
+ }
+ newarray[cfg->num_tags++] = newtag;
+ cfg->tagname = newarray;
+ return 1;
+}
+
+/** set a bit in a bit array */
+static void
+cfg_set_bit(uint8_t* bitlist, size_t len, int id)
+{
+ int pos = id/8;
+ log_assert((size_t)pos < len);
+ (void)len;
+ bitlist[pos] |= 1<<(id%8);
+}
+
+uint8_t* config_parse_taglist(struct config_file* cfg, char* str,
+ size_t* listlen)
+{
+ uint8_t* taglist = NULL;
+ size_t len = 0;
+ char* p, *s;
+
+ /* allocate */
+ if(cfg->num_tags == 0) {
+ log_err("parse taglist, but no tags defined");
+ return 0;
+ }
+ len = (size_t)(cfg->num_tags+7)/8;
+ taglist = calloc(1, len);
+ if(!taglist) {
+ log_err("out of memory");
+ return 0;
+ }
+
+ /* parse */
+ s = str;
+ while((p=strsep(&s, " \t\n")) != NULL) {
+ if(*p) {
+ int id = find_tag_id(cfg, p);
+ /* set this bit in the bitlist */
+ if(id == -1) {
+ log_err("unknown tag: %s", p);
+ free(taglist);
+ return 0;
+ }
+ cfg_set_bit(taglist, len, id);
+ }
+ }
+
+ *listlen = len;
+ return taglist;
+}
+
+char* config_taglist2str(struct config_file* cfg, uint8_t* taglist,
+ size_t taglen)
+{
+ char buf[10240];
+ size_t i, j, len = 0;
+ buf[0] = 0;
+ for(i=0; i<taglen; i++) {
+ if(taglist[i] == 0)
+ continue;
+ for(j=0; j<8; j++) {
+ if((taglist[i] & (1<<j)) != 0) {
+ size_t id = i*8 + j;
+ snprintf(buf+len, sizeof(buf)-len, "%s%s",
+ (len==0?"":" "), cfg->tagname[id]);
+ len += strlen(buf+len);
+ }
+ }
+ }
+ return strdup(buf);
+}
+
+int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
+ size_t list2len)
+{
+ size_t i;
+ if(!list1 || !list2)
+ return 0;
+ for(i=0; i<list1len && i<list2len; i++) {
+ if((list1[i] & list2[i]) != 0)
+ return 1;
+ }
+ return 0;
+}
+
void
config_apply(struct config_file* config)
{
diff --git a/contrib/unbound/util/config_file.h b/contrib/unbound/util/config_file.h
index ef823fb..07edff7 100644
--- a/contrib/unbound/util/config_file.h
+++ b/contrib/unbound/util/config_file.h
@@ -44,9 +44,12 @@
struct config_stub;
struct config_strlist;
struct config_str2list;
+struct config_str3list;
+struct config_strbytelist;
struct module_qstate;
struct sock_list;
struct ub_packed_rrset_key;
+struct regional;
/**
* The configuration options.
@@ -72,6 +75,8 @@ struct config_file {
int do_ip4;
/** do ip6 query support. */
int do_ip6;
+ /** prefer ip6 upstream queries. */
+ int prefer_ip6;
/** do udp query support. */
int do_udp;
/** do tcp query support. */
@@ -142,6 +147,8 @@ struct config_file {
int so_reuseport;
/** IP_TRANSPARENT socket option requested on port 53 sockets */
int ip_transparent;
+ /** IP_FREEBIND socket option request on port 53 sockets */
+ int ip_freebind;
/** number of interfaces to open. If 0 default all interfaces. */
int num_ifs;
@@ -289,10 +296,24 @@ struct config_file {
struct config_strlist* local_zones_nodefault;
/** local data RRs configured */
struct config_strlist* local_data;
+ /** local zone override types per netblock */
+ struct config_str3list* local_zone_overrides;
/** unblock lan zones (reverse lookups for AS112 zones) */
int unblock_lan_zones;
/** insecure lan zones (don't validate AS112 zones) */
int insecure_lan_zones;
+ /** list of zonename, tagbitlist */
+ struct config_strbytelist* local_zone_tags;
+ /** list of aclname, tagbitlist */
+ struct config_strbytelist* acl_tags;
+ /** list of aclname, tagname, localzonetype */
+ struct config_str3list* acl_tag_actions;
+ /** list of aclname, tagname, redirectdata */
+ struct config_str3list* acl_tag_datas;
+ /** tag list, array with tagname[i] is malloced string */
+ char** tagname;
+ /** number of items in the taglist */
+ int num_tags;
/** remote control section. enable toggle. */
int remote_control_enable;
@@ -358,6 +379,9 @@ struct config_file {
/** true to log dnstap FORWARDER_RESPONSE message events */
int dnstap_log_forwarder_response_messages;
+ /** true to disable DNSSEC lameness check in iterator */
+ int disable_dnssec_lame_check;
+
/** ratelimit 0 is off, otherwise qps (unless overridden) */
int ratelimit;
/** number of slabs for ratelimit cache */
@@ -421,6 +445,34 @@ struct config_str2list {
char* str2;
};
+/**
+ * List of three strings for config options
+ */
+struct config_str3list {
+ /** next item in list */
+ struct config_str3list* next;
+ /** first string */
+ char* str;
+ /** second string */
+ char* str2;
+ /** third string */
+ char* str3;
+};
+
+
+/**
+ * List of string, bytestring for config options
+ */
+struct config_strbytelist {
+ /** next item in list */
+ struct config_strbytelist* next;
+ /** first string */
+ char* str;
+ /** second bytestring */
+ uint8_t* str2;
+ size_t str2len;
+};
+
/** List head for strlist processing, used for append operation. */
struct config_strlist_head {
/** first in list of text items */
@@ -550,6 +602,10 @@ int cfg_strlist_append(struct config_strlist_head* list, char* item);
*/
int cfg_strlist_insert(struct config_strlist** head, char* item);
+/** insert with region for allocation. */
+int cfg_region_strlist_insert(struct regional* region,
+ struct config_strlist** head, char* item);
+
/**
* Insert string into str2list.
* @param head: pointer to str2list head variable.
@@ -560,6 +616,28 @@ int cfg_strlist_insert(struct config_strlist** head, char* item);
int cfg_str2list_insert(struct config_str2list** head, char* item, char* i2);
/**
+ * Insert string into str3list.
+ * @param head: pointer to str3list head variable.
+ * @param item: new item. malloced by caller. If NULL the insertion fails.
+ * @param i2: 2nd string, malloced by caller. If NULL the insertion fails.
+ * @param i3: 3rd string, malloced by caller. If NULL the insertion fails.
+ * @return: true on success.
+ */
+int cfg_str3list_insert(struct config_str3list** head, char* item, char* i2,
+ char* i3);
+
+/**
+ * Insert string into strbytelist.
+ * @param head: pointer to strbytelist head variable.
+ * @param item: new item. malloced by caller. If NULL the insertion fails.
+ * @param i2: 2nd string, malloced by caller. If NULL the insertion fails.
+ * @param i2len: length of the i2 bytestring.
+ * @return: true on success.
+ */
+int cfg_strbytelist_insert(struct config_strbytelist** head, char* item,
+ uint8_t* i2, size_t i2len);
+
+/**
* Find stub in config list, also returns prevptr (for deletion).
* @param pp: call routine with pointer to a pointer to the start of the list,
* if the stub is found, on exit, the value contains a pointer to the
@@ -583,6 +661,15 @@ void config_delstrlist(struct config_strlist* list);
void config_deldblstrlist(struct config_str2list* list);
/**
+ * Delete items in config triple string list.
+ * @param list: list.
+ */
+void config_deltrplstrlist(struct config_str3list* list);
+
+/** delete stringbytelist */
+void config_del_strbytelist(struct config_strbytelist* list);
+
+/**
* Delete a stub item
* @param p: stub item
*/
@@ -625,6 +712,54 @@ int cfg_count_numbers(const char* str);
int cfg_parse_memsize(const char* str, size_t* res);
/**
+ * Add a tag name to the config. It is added at the end with a new ID value.
+ * @param cfg: the config structure.
+ * @param tag: string (which is copied) with the name.
+ * @return: false on alloc failure.
+ */
+int config_add_tag(struct config_file* cfg, const char* tag);
+
+/**
+ * Find tag ID in the tag list.
+ * @param cfg: the config structure.
+ * @param tag: string with tag name to search for.
+ * @return: 0..(num_tags-1) with tag ID, or -1 if tagname is not found.
+ */
+int find_tag_id(struct config_file* cfg, const char* tag);
+
+/**
+ * parse taglist from string into bytestring with bitlist.
+ * @param cfg: the config structure (with tagnames)
+ * @param str: the string to parse. Parse puts 0 bytes in string.
+ * @param listlen: returns length of in bytes.
+ * @return malloced bytes with a bitlist of the tags. or NULL on parse error
+ * or malloc failure.
+ */
+uint8_t* config_parse_taglist(struct config_file* cfg, char* str,
+ size_t* listlen);
+
+/**
+ * convert tag bitlist to a malloced string with tag names. For debug output.
+ * @param cfg: the config structure (with tagnames)
+ * @param taglist: the tag bitlist.
+ * @param len: length of the tag bitlist.
+ * @return malloced string or NULL.
+ */
+char* config_taglist2str(struct config_file* cfg, uint8_t* taglist,
+ size_t len);
+
+/**
+ * see if two taglists intersect (have tags in common).
+ * @param list1: first tag bitlist.
+ * @param list1len: length in bytes of first list.
+ * @param list2: second tag bitlist.
+ * @param list2len: length in bytes of second list.
+ * @return true if there are tags in common, 0 if not.
+ */
+int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
+ size_t list2len);
+
+/**
* Parse local-zone directive into two strings and register it in the config.
* @param cfg: to put it in.
* @param val: argument strings to local-zone, "example.com nodefault".
diff --git a/contrib/unbound/util/configlexer.lex b/contrib/unbound/util/configlexer.lex
index ad49e37..a8d4a96 100644
--- a/contrib/unbound/util/configlexer.lex
+++ b/contrib/unbound/util/configlexer.lex
@@ -9,6 +9,9 @@
*/
#include "config.h"
+/* because flex keeps having sign-unsigned compare problems that are unfixed*/
+#pragma GCC diagnostic ignored "-Wsign-compare"
+
#include <ctype.h>
#include <string.h>
#include <strings.h>
@@ -218,6 +221,7 @@ outgoing-num-tcp{COLON} { YDVAR(1, VAR_OUTGOING_NUM_TCP) }
incoming-num-tcp{COLON} { YDVAR(1, VAR_INCOMING_NUM_TCP) }
do-ip4{COLON} { YDVAR(1, VAR_DO_IP4) }
do-ip6{COLON} { YDVAR(1, VAR_DO_IP6) }
+prefer-ip6{COLON} { YDVAR(1, VAR_PREFER_IP6) }
do-udp{COLON} { YDVAR(1, VAR_DO_UDP) }
do-tcp{COLON} { YDVAR(1, VAR_DO_TCP) }
tcp-upstream{COLON} { YDVAR(1, VAR_TCP_UPSTREAM) }
@@ -236,6 +240,7 @@ so-rcvbuf{COLON} { YDVAR(1, VAR_SO_RCVBUF) }
so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) }
so-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) }
ip-transparent{COLON} { YDVAR(1, VAR_IP_TRANSPARENT) }
+ip-freebind{COLON} { YDVAR(1, VAR_IP_FREEBIND) }
chroot{COLON} { YDVAR(1, VAR_CHROOT) }
username{COLON} { YDVAR(1, VAR_USERNAME) }
directory{COLON} { YDVAR(1, VAR_DIRECTORY) }
@@ -344,6 +349,12 @@ rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
max-udp-size{COLON} { YDVAR(1, VAR_MAX_UDP_SIZE) }
dns64-prefix{COLON} { YDVAR(1, VAR_DNS64_PREFIX) }
dns64-synthall{COLON} { YDVAR(1, VAR_DNS64_SYNTHALL) }
+define-tag{COLON} { YDVAR(1, VAR_DEFINE_TAG) }
+local-zone-tag{COLON} { YDVAR(2, VAR_LOCAL_ZONE_TAG) }
+access-control-tag{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_TAG) }
+access-control-tag-action{COLON} { YDVAR(3, VAR_ACCESS_CONTROL_TAG_ACTION) }
+access-control-tag-data{COLON} { YDVAR(3, VAR_ACCESS_CONTROL_TAG_DATA) }
+local-zone-override{COLON} { YDVAR(3, VAR_LOCAL_ZONE_OVERRIDE) }
dnstap{COLON} { YDVAR(0, VAR_DNSTAP) }
dnstap-enable{COLON} { YDVAR(1, VAR_DNSTAP_ENABLE) }
dnstap-socket-path{COLON} { YDVAR(1, VAR_DNSTAP_SOCKET_PATH) }
@@ -363,6 +374,7 @@ dnstap-log-forwarder-query-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) }
dnstap-log-forwarder-response-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
+disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) }
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
ratelimit-slabs{COLON} { YDVAR(1, VAR_RATELIMIT_SLABS) }
ratelimit-size{COLON} { YDVAR(1, VAR_RATELIMIT_SIZE) }
diff --git a/contrib/unbound/util/configparser.y b/contrib/unbound/util/configparser.y
index ea7acdb..7240ee4 100644
--- a/contrib/unbound/util/configparser.y
+++ b/contrib/unbound/util/configparser.y
@@ -69,7 +69,7 @@ extern struct config_parser_state* cfg_parser;
%token <str> STRING_ARG
%token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT
%token VAR_OUTGOING_RANGE VAR_INTERFACE
-%token VAR_DO_IP4 VAR_DO_IP6 VAR_DO_UDP VAR_DO_TCP
+%token VAR_DO_IP4 VAR_DO_IP6 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP
%token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS
%token VAR_CHROOT VAR_USERNAME VAR_DIRECTORY VAR_LOGFILE VAR_PIDFILE
%token VAR_MSG_CACHE_SIZE VAR_MSG_CACHE_SLABS VAR_NUM_QUERIES_PER_THREAD
@@ -121,10 +121,13 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
+%token VAR_DISABLE_DNSSEC_LAME_CHECK
%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE
%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN VAR_RATELIMIT_FACTOR
%token VAR_CAPS_WHITELIST VAR_CACHE_MAX_NEGATIVE_TTL VAR_PERMIT_SMALL_HOLDDOWN
-%token VAR_QNAME_MINIMISATION
+%token VAR_QNAME_MINIMISATION VAR_IP_FREEBIND VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG
+%token VAR_ACCESS_CONTROL_TAG VAR_LOCAL_ZONE_OVERRIDE
+%token VAR_ACCESS_CONTROL_TAG_ACTION VAR_ACCESS_CONTROL_TAG_DATA
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -143,7 +146,8 @@ contents_server: contents_server content_server
| ;
content_server: server_num_threads | server_verbosity | server_port |
server_outgoing_range | server_do_ip4 |
- server_do_ip6 | server_do_udp | server_do_tcp |
+ server_do_ip6 | server_prefer_ip6 |
+ server_do_udp | server_do_tcp |
server_tcp_mss | server_outgoing_tcp_mss |
server_interface | server_chroot | server_username |
server_directory | server_logfile | server_pidfile |
@@ -191,7 +195,11 @@ content_server: server_num_threads | server_verbosity | server_port |
server_ratelimit_size | server_ratelimit_for_domain |
server_ratelimit_below_domain | server_ratelimit_factor |
server_caps_whitelist | server_cache_max_negative_ttl |
- server_permit_small_holddown | server_qname_minimisation
+ server_permit_small_holddown | server_qname_minimisation |
+ server_ip_freebind | server_define_tag | server_local_zone_tag |
+ server_disable_dnssec_lame_check | server_access_control_tag |
+ server_local_zone_override | server_access_control_tag_action |
+ server_access_control_tag_data
;
stubstart: VAR_STUB_ZONE
{
@@ -399,6 +407,15 @@ server_do_tcp: VAR_DO_TCP STRING_ARG
free($2);
}
;
+server_prefer_ip6: VAR_PREFER_IP6 STRING_ARG
+ {
+ OUTYY(("P(server_prefer_ip6:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->prefer_ip6 = (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
server_tcp_mss: VAR_TCP_MSS STRING_ARG
{
OUTYY(("P(server_tcp_mss:%s)\n", $2));
@@ -518,6 +535,23 @@ server_directory: VAR_DIRECTORY STRING_ARG
OUTYY(("P(server_directory:%s)\n", $2));
free(cfg_parser->cfg->directory);
cfg_parser->cfg->directory = $2;
+ /* change there right away for includes relative to this */
+ if($2[0]) {
+ char* d;
+#ifdef UB_ON_WINDOWS
+ w_config_adjust_directory(cfg_parser->cfg);
+#endif
+ d = cfg_parser->cfg->directory;
+ /* adjust directory if we have already chroot,
+ * like, we reread after sighup */
+ if(cfg_parser->chroot && cfg_parser->chroot[0] &&
+ strncmp(d, cfg_parser->chroot, strlen(
+ cfg_parser->chroot)) == 0)
+ d += strlen(cfg_parser->chroot);
+ if(chdir(d))
+ log_err("cannot chdir to directory: %s (%s)",
+ d, strerror(errno));
+ }
}
;
server_logfile: VAR_LOGFILE STRING_ARG
@@ -662,6 +696,16 @@ server_ip_transparent: VAR_IP_TRANSPARENT STRING_ARG
free($2);
}
;
+server_ip_freebind: VAR_IP_FREEBIND STRING_ARG
+ {
+ OUTYY(("P(server_ip_freebind:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->ip_freebind =
+ (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
server_edns_buffer_size: VAR_EDNS_BUFFER_SIZE STRING_ARG
{
OUTYY(("P(server_edns_buffer_size:%s)\n", $2));
@@ -1203,12 +1247,16 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
if(strcmp($3, "static")!=0 && strcmp($3, "deny")!=0 &&
strcmp($3, "refuse")!=0 && strcmp($3, "redirect")!=0 &&
strcmp($3, "transparent")!=0 && strcmp($3, "nodefault")!=0
- && strcmp($3, "typetransparent")!=0 &&
- strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0)
+ && strcmp($3, "typetransparent")!=0
+ && strcmp($3, "always_transparent")!=0
+ && strcmp($3, "always_refuse")!=0
+ && strcmp($3, "always_nxdomain")!=0
+ && strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0)
yyerror("local-zone type: expected static, deny, "
"refuse, redirect, transparent, "
- "typetransparent, inform, inform_deny "
- "or nodefault");
+ "typetransparent, inform, inform_deny, "
+ "always_transparent, always_refuse, "
+ "always_nxdomain or nodefault");
else if(strcmp($3, "nodefault")==0) {
if(!cfg_strlist_insert(&cfg_parser->cfg->
local_zones_nodefault, $2))
@@ -1286,6 +1334,94 @@ server_dns64_synthall: VAR_DNS64_SYNTHALL STRING_ARG
free($2);
}
;
+server_define_tag: VAR_DEFINE_TAG STRING_ARG
+ {
+ char* p, *s = $2;
+ OUTYY(("P(server_define_tag:%s)\n", $2));
+ while((p=strsep(&s, " \t\n")) != NULL) {
+ if(*p) {
+ if(!config_add_tag(cfg_parser->cfg, p))
+ yyerror("could not define-tag, "
+ "out of memory");
+ }
+ }
+ free($2);
+ }
+ ;
+server_local_zone_tag: VAR_LOCAL_ZONE_TAG STRING_ARG STRING_ARG
+ {
+ size_t len = 0;
+ uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3,
+ &len);
+ free($3);
+ OUTYY(("P(server_local_zone_tag:%s)\n", $2));
+ if(!bitlist)
+ yyerror("could not parse tags, (define-tag them first)");
+ if(bitlist) {
+ if(!cfg_strbytelist_insert(
+ &cfg_parser->cfg->local_zone_tags,
+ $2, bitlist, len)) {
+ yyerror("out of memory");
+ free($2);
+ }
+ }
+ }
+ ;
+server_access_control_tag: VAR_ACCESS_CONTROL_TAG STRING_ARG STRING_ARG
+ {
+ size_t len = 0;
+ uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3,
+ &len);
+ free($3);
+ OUTYY(("P(server_access_control_tag:%s)\n", $2));
+ if(!bitlist)
+ yyerror("could not parse tags, (define-tag them first)");
+ if(bitlist) {
+ if(!cfg_strbytelist_insert(
+ &cfg_parser->cfg->acl_tags,
+ $2, bitlist, len)) {
+ yyerror("out of memory");
+ free($2);
+ }
+ }
+ }
+ ;
+server_access_control_tag_action: VAR_ACCESS_CONTROL_TAG_ACTION STRING_ARG STRING_ARG STRING_ARG
+ {
+ OUTYY(("P(server_access_control_tag_action:%s %s %s)\n", $2, $3, $4));
+ if(!cfg_str3list_insert(&cfg_parser->cfg->acl_tag_actions,
+ $2, $3, $4)) {
+ yyerror("out of memory");
+ free($2);
+ free($3);
+ free($4);
+ }
+ }
+ ;
+server_access_control_tag_data: VAR_ACCESS_CONTROL_TAG_DATA STRING_ARG STRING_ARG STRING_ARG
+ {
+ OUTYY(("P(server_access_control_tag_data:%s %s %s)\n", $2, $3, $4));
+ if(!cfg_str3list_insert(&cfg_parser->cfg->acl_tag_datas,
+ $2, $3, $4)) {
+ yyerror("out of memory");
+ free($2);
+ free($3);
+ free($4);
+ }
+ }
+ ;
+server_local_zone_override: VAR_LOCAL_ZONE_OVERRIDE STRING_ARG STRING_ARG STRING_ARG
+ {
+ OUTYY(("P(server_local_zone_override:%s %s %s)\n", $2, $3, $4));
+ if(!cfg_str3list_insert(&cfg_parser->cfg->local_zone_overrides,
+ $2, $3, $4)) {
+ yyerror("out of memory");
+ free($2);
+ free($3);
+ free($4);
+ }
+ }
+ ;
server_ratelimit: VAR_RATELIMIT STRING_ARG
{
OUTYY(("P(server_ratelimit:%s)\n", $2));
@@ -1643,6 +1779,15 @@ py_script: VAR_PYTHON_SCRIPT STRING_ARG
free(cfg_parser->cfg->python_script);
cfg_parser->cfg->python_script = $2;
}
+server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
+ {
+ OUTYY(("P(disable_dnssec_lame_check:%s)\n", $2));
+ if (strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->disable_dnssec_lame_check =
+ (strcmp($2, "yes")==0);
+ free($2);
+ }
%%
/* parse helper routines could be here */
diff --git a/contrib/unbound/util/data/dname.c b/contrib/unbound/util/data/dname.c
index 79bf52a..8fc475f 100644
--- a/contrib/unbound/util/data/dname.c
+++ b/contrib/unbound/util/data/dname.c
@@ -256,11 +256,13 @@ dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2)
log_assert(len1 == len2 && len1 != 0);
/* compare labels */
while(len1--) {
- if(tolower((unsigned char)*d1++) != tolower((unsigned char)*d2++)) {
- if(tolower((unsigned char)d1[-1]) < tolower((unsigned char)d2[-1]))
+ if(tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) {
+ if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2))
return -1;
return 1;
}
+ d1++;
+ d2++;
}
len1 = *d1++;
len2 = *d2++;
@@ -281,8 +283,10 @@ dname_query_hash(uint8_t* dname, hashvalue_t h)
log_assert(lablen <= LDNS_MAX_LABELLEN);
labuf[0] = lablen;
i=0;
- while(lablen--)
- labuf[++i] = (uint8_t)tolower((unsigned char)*dname++);
+ while(lablen--) {
+ labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
+ dname++;
+ }
h = hashlittle(labuf, labuf[0] + 1, h);
lablen = *dname++;
}
@@ -309,8 +313,10 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_t h)
log_assert(lablen <= LDNS_MAX_LABELLEN);
labuf[0] = lablen;
i=0;
- while(lablen--)
- labuf[++i] = (uint8_t)tolower((unsigned char)*dname++);
+ while(lablen--) {
+ labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
+ dname++;
+ }
h = hashlittle(labuf, labuf[0] + 1, h);
lablen = *dname++;
}
diff --git a/contrib/unbound/util/data/msgencode.c b/contrib/unbound/util/data/msgencode.c
index 43464e9..034bb24 100644
--- a/contrib/unbound/util/data/msgencode.c
+++ b/contrib/unbound/util/data/msgencode.c
@@ -717,16 +717,23 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
uint16_t
calc_edns_field_size(struct edns_data* edns)
{
+ size_t rdatalen = 0;
+ struct edns_option* opt;
if(!edns || !edns->edns_present)
return 0;
- /* domain root '.' + type + class + ttl + rdatalen(=0) */
- return 1 + 2 + 2 + 4 + 2;
+ for(opt = edns->opt_list; opt; opt = opt->next) {
+ rdatalen += 4 + opt->opt_len;
+ }
+ /* domain root '.' + type + class + ttl + rdatalen */
+ return 1 + 2 + 2 + 4 + 2 + rdatalen;
}
void
attach_edns_record(sldns_buffer* pkt, struct edns_data* edns)
{
size_t len;
+ size_t rdatapos;
+ struct edns_option* opt;
if(!edns || !edns->edns_present)
return;
/* inc additional count */
@@ -742,7 +749,18 @@ attach_edns_record(sldns_buffer* pkt, struct edns_data* edns)
sldns_buffer_write_u8(pkt, edns->ext_rcode); /* ttl */
sldns_buffer_write_u8(pkt, edns->edns_version);
sldns_buffer_write_u16(pkt, edns->bits);
+ rdatapos = sldns_buffer_position(pkt);
sldns_buffer_write_u16(pkt, 0); /* rdatalen */
+ /* write rdata */
+ for(opt=edns->opt_list; opt; opt=opt->next) {
+ sldns_buffer_write_u16(pkt, opt->opt_code);
+ sldns_buffer_write_u16(pkt, opt->opt_len);
+ if(opt->opt_len != 0)
+ sldns_buffer_write(pkt, opt->opt_data, opt->opt_len);
+ }
+ if(edns->opt_list)
+ sldns_buffer_write_u16_at(pkt, rdatapos,
+ sldns_buffer_position(pkt)-rdatapos-2);
sldns_buffer_flip(pkt);
}
diff --git a/contrib/unbound/util/data/msgparse.c b/contrib/unbound/util/data/msgparse.c
index 108c9da..1d565c1 100644
--- a/contrib/unbound/util/data/msgparse.c
+++ b/contrib/unbound/util/data/msgparse.c
@@ -38,6 +38,7 @@
*/
#include "config.h"
#include "util/data/msgparse.h"
+#include "util/data/msgreply.h"
#include "util/data/dname.h"
#include "util/data/packed_rrset.h"
#include "util/storage/lookup3.h"
@@ -933,13 +934,41 @@ parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region)
return 0;
}
+/** parse EDNS options from EDNS wireformat rdata */
+static int
+parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len,
+ struct edns_data* edns, struct regional* region)
+{
+ /* while still more options, and have code+len to read */
+ /* ignores partial content (i.e. rdata len 3) */
+ while(rdata_len >= 4) {
+ uint16_t opt_code = sldns_read_uint16(rdata_ptr);
+ uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
+ rdata_ptr += 4;
+ rdata_len -= 4;
+ if(opt_len > rdata_len)
+ break; /* option code partial */
+ if(!edns_opt_append(edns, region, opt_code, opt_len,
+ rdata_ptr)) {
+ log_err("out of memory");
+ return 0;
+ }
+ rdata_ptr += opt_len;
+ rdata_len -= opt_len;
+ }
+ return 1;
+}
+
int
-parse_extract_edns(struct msg_parse* msg, struct edns_data* edns)
+parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
+ struct regional* region)
{
struct rrset_parse* rrset = msg->rrset_first;
struct rrset_parse* prev = 0;
struct rrset_parse* found = 0;
struct rrset_parse* found_prev = 0;
+ size_t rdata_len;
+ uint8_t* rdata_ptr;
/* since the class encodes the UDP size, we cannot use hash table to
* find the EDNS OPT record. Scan the packet. */
while(rrset) {
@@ -986,13 +1015,25 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns)
edns->edns_version = found->rr_last->ttl_data[1];
edns->bits = sldns_read_uint16(&found->rr_last->ttl_data[2]);
edns->udp_size = ntohs(found->rrset_class);
- /* ignore rdata and rrsigs */
+ edns->opt_list = NULL;
+
+ /* take the options */
+ rdata_len = found->rr_first->size;
+ rdata_ptr = found->rr_first->ttl_data+6;
+ if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
+ return 0;
+
+ /* ignore rrsigs */
+
return 0;
}
int
-parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns)
+parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
+ struct regional* region)
{
+ size_t rdata_len;
+ uint8_t* rdata_ptr;
log_assert(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) == 1);
log_assert(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0);
log_assert(LDNS_NSCOUNT(sldns_buffer_begin(pkt)) == 0);
@@ -1017,6 +1058,17 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns)
edns->ext_rcode = sldns_buffer_read_u8(pkt); /* ttl used for bits */
edns->edns_version = sldns_buffer_read_u8(pkt);
edns->bits = sldns_buffer_read_u16(pkt);
- /* ignore rdata and rrsigs */
+ edns->opt_list = NULL;
+
+ /* take the options */
+ rdata_len = sldns_buffer_read_u16(pkt);
+ if(sldns_buffer_remaining(pkt) < rdata_len)
+ return LDNS_RCODE_FORMERR;
+ rdata_ptr = sldns_buffer_current(pkt);
+ if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
+ return LDNS_RCODE_SERVFAIL;
+
+ /* ignore rrsigs */
+
return 0;
}
diff --git a/contrib/unbound/util/data/msgparse.h b/contrib/unbound/util/data/msgparse.h
index 44497c8..cae988f 100644
--- a/contrib/unbound/util/data/msgparse.h
+++ b/contrib/unbound/util/data/msgparse.h
@@ -69,6 +69,7 @@ struct sldns_buffer;
struct rrset_parse;
struct rr_parse;
struct regional;
+struct edns_option;
/** number of buckets in parse rrset hash table. Must be power of 2. */
#define PARSE_TABLE_SIZE 32
@@ -202,7 +203,8 @@ struct rr_parse {
/**
* EDNS data storage
- * EDNS rdata is ignored.
+ * rdata is parsed in a list (has accessor functions). allocated in a
+ * region.
*/
struct edns_data {
/** if EDNS OPT record was present */
@@ -215,6 +217,22 @@ struct edns_data {
uint16_t bits;
/** UDP reassembly size. */
uint16_t udp_size;
+ /** rdata element list, or NULL if none */
+ struct edns_option* opt_list;
+};
+
+/**
+ * EDNS option
+ */
+struct edns_option {
+ /** next item in list */
+ struct edns_option* next;
+ /** type of this edns option */
+ uint16_t opt_code;
+ /** length of this edns option (cannot exceed uint16 in encoding) */
+ size_t opt_len;
+ /** data of this edns option; allocated in region, or NULL if len=0 */
+ uint8_t* opt_data;
};
/**
@@ -249,10 +267,12 @@ int parse_packet(struct sldns_buffer* pkt, struct msg_parse* msg,
* @param msg: parsed message structure. Modified on exit, if EDNS was present
* it is removed from the additional section.
* @param edns: the edns data is stored here. Does not have to be initialised.
+ * @param region: region to alloc results in (edns option contents)
* @return: 0 on success. or an RCODE on an error.
* RCODE formerr if OPT in wrong section, and so on.
*/
-int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns);
+int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
+ struct regional* region);
/**
* If EDNS data follows a query section, extract it and initialize edns struct.
@@ -260,10 +280,12 @@ int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns);
* section. At end, right after EDNS data or no movement if failed.
* @param edns: the edns data allocated by the caller. Does not have to be
* initialised.
+ * @param region: region to alloc results in (edns option contents)
* @return: 0 on success, or an RCODE on error.
* RCODE formerr if OPT is badly formatted and so on.
*/
-int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns);
+int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns,
+ struct regional* region);
/**
* Calculate hash value for rrset in packet.
diff --git a/contrib/unbound/util/data/msgreply.c b/contrib/unbound/util/data/msgreply.c
index 06593ff..f8a2491 100644
--- a/contrib/unbound/util/data/msgreply.c
+++ b/contrib/unbound/util/data/msgreply.c
@@ -461,7 +461,7 @@ int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc,
if((ret = parse_packet(pkt, msg, region)) != 0) {
return ret;
}
- if((ret = parse_extract_edns(msg, edns)) != 0)
+ if((ret = parse_extract_edns(msg, edns, region)) != 0)
return ret;
/* parse OK, allocate return structures */
@@ -857,3 +857,155 @@ reply_all_rrsets_secure(struct reply_info* rep)
}
return 1;
}
+
+int edns_opt_append(struct edns_data* edns, struct regional* region,
+ uint16_t code, size_t len, uint8_t* data)
+{
+ struct edns_option** prevp;
+ struct edns_option* opt;
+
+ /* allocate new element */
+ opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
+ if(!opt)
+ return 0;
+ opt->next = NULL;
+ opt->opt_code = code;
+ opt->opt_len = len;
+ opt->opt_data = regional_alloc_init(region, data, len);
+ if(!opt->opt_data)
+ return 0;
+
+ /* append at end of list */
+ prevp = &edns->opt_list;
+ while(*prevp != NULL)
+ prevp = &((*prevp)->next);
+ *prevp = opt;
+ return 1;
+}
+
+int edns_opt_inplace_reply(struct edns_data* edns, struct regional* region)
+{
+ (void)region;
+ /* remove all edns options from the reply, because only the
+ * options that we understand should be in the reply
+ * (sec 6.1.2 RFC 6891) */
+ edns->opt_list = NULL;
+ return 1;
+}
+
+struct edns_option* edns_opt_copy_region(struct edns_option* list,
+ struct regional* region)
+{
+ struct edns_option* result = NULL, *cur = NULL, *s;
+ while(list) {
+ /* copy edns option structure */
+ s = regional_alloc_init(region, list, sizeof(*list));
+ if(!s) return NULL;
+ s->next = NULL;
+
+ /* copy option data */
+ if(s->opt_data) {
+ s->opt_data = regional_alloc_init(region, s->opt_data,
+ s->opt_len);
+ if(!s->opt_data)
+ return NULL;
+ }
+
+ /* link into list */
+ if(cur)
+ cur->next = s;
+ else result = s;
+ cur = s;
+
+ /* examine next element */
+ list = list->next;
+ }
+ return result;
+}
+
+int edns_opt_compare(struct edns_option* p, struct edns_option* q)
+{
+ if(!p && !q) return 0;
+ if(!p) return -1;
+ if(!q) return 1;
+ log_assert(p && q);
+ if(p->opt_code != q->opt_code)
+ return (int)q->opt_code - (int)p->opt_code;
+ if(p->opt_len != q->opt_len)
+ return (int)q->opt_len - (int)p->opt_len;
+ if(p->opt_len != 0)
+ return memcmp(p->opt_data, q->opt_data, p->opt_len);
+ return 0;
+}
+
+int edns_opt_list_compare(struct edns_option* p, struct edns_option* q)
+{
+ int r;
+ while(p && q) {
+ r = edns_opt_compare(p, q);
+ if(r != 0)
+ return r;
+ p = p->next;
+ q = q->next;
+ }
+ if(p || q) {
+ /* uneven length lists */
+ if(p) return 1;
+ if(q) return -1;
+ }
+ return 0;
+}
+
+void edns_opt_list_free(struct edns_option* list)
+{
+ struct edns_option* n;
+ while(list) {
+ free(list->opt_data);
+ n = list->next;
+ free(list);
+ list = n;
+ }
+}
+
+struct edns_option* edns_opt_copy_alloc(struct edns_option* list)
+{
+ struct edns_option* result = NULL, *cur = NULL, *s;
+ while(list) {
+ /* copy edns option structure */
+ s = memdup(list, sizeof(*list));
+ if(!s) {
+ edns_opt_list_free(result);
+ return NULL;
+ }
+ s->next = NULL;
+
+ /* copy option data */
+ if(s->opt_data) {
+ s->opt_data = memdup(s->opt_data, s->opt_len);
+ if(!s->opt_data) {
+ edns_opt_list_free(result);
+ return NULL;
+ }
+ }
+
+ /* link into list */
+ if(cur)
+ cur->next = s;
+ else result = s;
+ cur = s;
+
+ /* examine next element */
+ list = list->next;
+ }
+ return result;
+}
+
+struct edns_option* edns_opt_find(struct edns_option* list, uint16_t code)
+{
+ struct edns_option* p;
+ for(p=list; p; p=p->next) {
+ if(p->opt_code == code)
+ return p;
+ }
+ return NULL;
+}
diff --git a/contrib/unbound/util/data/msgreply.h b/contrib/unbound/util/data/msgreply.h
index 7088979..b542b75 100644
--- a/contrib/unbound/util/data/msgreply.h
+++ b/contrib/unbound/util/data/msgreply.h
@@ -437,4 +437,56 @@ void log_dns_msg(const char* str, struct query_info* qinfo,
void log_query_info(enum verbosity_value v, const char* str,
struct query_info* qinf);
+/**
+ * Append edns option to edns data structure
+ */
+int edns_opt_append(struct edns_data* edns, struct regional* region,
+ uint16_t code, size_t len, uint8_t* data);
+
+/**
+ * Find edns option in edns list
+ * @param list: list of edns options (eg. edns.opt_list)
+ * @param code: opt code to find.
+ * @return NULL or the edns_option element.
+ */
+struct edns_option* edns_opt_find(struct edns_option* list, uint16_t code);
+
+/**
+ * Transform edns data structure from query structure into reply structure.
+ * In place transform, for errors and cache replies.
+ * @param edns: on input contains the edns from the query. On output contains
+ * the edns for the answer. Add new options to the opt_list to put them
+ * in the answer (allocated in the region, with edns_opt_append).
+ * @param region: to allocate stuff in.
+ * @return false on failure (servfail to client, or for some error encodings,
+ * no EDNS options in the answer).
+ */
+int edns_opt_inplace_reply(struct edns_data* edns, struct regional* region);
+
+/**
+ * Copy edns option list allocated to the new region
+ */
+struct edns_option* edns_opt_copy_region(struct edns_option* list,
+ struct regional* region);
+
+/**
+ * Copy edns option list allocated with malloc
+ */
+struct edns_option* edns_opt_copy_alloc(struct edns_option* list);
+
+/**
+ * Free edns option list allocated with malloc
+ */
+void edns_opt_list_free(struct edns_option* list);
+
+/**
+ * Compare an edns option. (not entire list). Also compares contents.
+ */
+int edns_opt_compare(struct edns_option* p, struct edns_option* q);
+
+/**
+ * Compare edns option lists, also the order and contents of edns-options.
+ */
+int edns_opt_list_compare(struct edns_option* p, struct edns_option* q);
+
#endif /* UTIL_DATA_MSGREPLY_H */
diff --git a/contrib/unbound/util/fptr_wlist.c b/contrib/unbound/util/fptr_wlist.c
index 1397e9c..80a23f2 100644
--- a/contrib/unbound/util/fptr_wlist.c
+++ b/contrib/unbound/util/fptr_wlist.c
@@ -78,6 +78,9 @@
#ifdef WITH_PYTHONMODULE
#include "pythonmod/pythonmod.h"
#endif
+#ifdef USE_CACHEDB
+#include "cachedb/cachedb.h"
+#endif
int
fptr_whitelist_comm_point(comm_point_callback_t *fptr)
@@ -264,8 +267,8 @@ int
fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
- struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen,
+ struct edns_option* opt_list, struct sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen,
struct module_qstate* q))
{
if(fptr == &worker_send_query) return 1;
@@ -315,6 +318,9 @@ fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_init) return 1;
#endif
+#ifdef USE_CACHEDB
+ else if(fptr == &cachedb_init) return 1;
+#endif
return 0;
}
@@ -327,6 +333,9 @@ fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_deinit) return 1;
#endif
+#ifdef USE_CACHEDB
+ else if(fptr == &cachedb_deinit) return 1;
+#endif
return 0;
}
@@ -340,6 +349,9 @@ fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate,
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_operate) return 1;
#endif
+#ifdef USE_CACHEDB
+ else if(fptr == &cachedb_operate) return 1;
+#endif
return 0;
}
@@ -353,6 +365,9 @@ fptr_whitelist_mod_inform_super(void (*fptr)(
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_inform_super) return 1;
#endif
+#ifdef USE_CACHEDB
+ else if(fptr == &cachedb_inform_super) return 1;
+#endif
return 0;
}
@@ -366,6 +381,9 @@ fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate,
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_clear) return 1;
#endif
+#ifdef USE_CACHEDB
+ else if(fptr == &cachedb_clear) return 1;
+#endif
return 0;
}
@@ -378,6 +396,9 @@ fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_get_mem) return 1;
#endif
+#ifdef USE_CACHEDB
+ else if(fptr == &cachedb_get_mem) return 1;
+#endif
return 0;
}
diff --git a/contrib/unbound/util/fptr_wlist.h b/contrib/unbound/util/fptr_wlist.h
index 10de5d8..98ca21b 100644
--- a/contrib/unbound/util/fptr_wlist.h
+++ b/contrib/unbound/util/fptr_wlist.h
@@ -212,7 +212,7 @@ int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr);
int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
- struct sockaddr_storage* addr, socklen_t addrlen,
+ struct edns_option*, struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen,
struct module_qstate* q));
diff --git a/contrib/unbound/util/iana_ports.inc b/contrib/unbound/util/iana_ports.inc
index df5a560..0ac3efb 100644
--- a/contrib/unbound/util/iana_ports.inc
+++ b/contrib/unbound/util/iana_ports.inc
@@ -1186,6 +1186,7 @@
1525,
1526,
1527,
+1528,
1529,
1530,
1531,
@@ -3844,6 +3845,8 @@
4412,
4413,
4416,
+4418,
+4420,
4425,
4426,
4430,
@@ -3904,6 +3907,7 @@
4599,
4600,
4601,
+4621,
4658,
4659,
4660,
@@ -4222,6 +4226,7 @@
5436,
5437,
5443,
+5450,
5453,
5454,
5455,
@@ -4522,7 +4527,6 @@
6786,
6787,
6788,
-6789,
6790,
6791,
6801,
@@ -4598,6 +4602,7 @@
7201,
7227,
7235,
+7244,
7262,
7272,
7273,
@@ -4651,6 +4656,7 @@
7570,
7574,
7588,
+7606,
7624,
7627,
7628,
@@ -5269,6 +5275,7 @@
23004,
23005,
23272,
+23294,
23333,
23400,
23401,
@@ -5418,6 +5425,7 @@
44900,
45000,
45054,
+45514,
45678,
45825,
45966,
diff --git a/contrib/unbound/util/module.h b/contrib/unbound/util/module.h
index b9dde36..c3ce8a4 100644
--- a/contrib/unbound/util/module.h
+++ b/contrib/unbound/util/module.h
@@ -214,6 +214,8 @@ struct module_env {
* EDNS, the answer is likely to be useless for this domain.
* @param nocaps: do not use caps_for_id, use the qname as given.
* (ignored if caps_for_id is disabled).
+ * @param opt_list: set these EDNS options on the outgoing packet.
+ * or NULL if none (the list is deep-copied).
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: delegation point name.
@@ -226,9 +228,9 @@ struct module_env {
*/
struct outbound_entry* (*send_query)(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
- int want_dnssec, int nocaps, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* zone, size_t zonelen,
- struct module_qstate* q);
+ int want_dnssec, int nocaps, struct edns_option* opt_list,
+ struct sockaddr_storage* addr, socklen_t addrlen,
+ uint8_t* zone, size_t zonelen, struct module_qstate* q);
/**
* Detach-subqueries.
diff --git a/contrib/unbound/util/net_help.c b/contrib/unbound/util/net_help.c
index eb03cd0..2485989 100644
--- a/contrib/unbound/util/net_help.c
+++ b/contrib/unbound/util/net_help.c
@@ -783,7 +783,7 @@ void* outgoing_ssl_fd(void* sslctx, int fd)
#endif
}
-#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
+#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
/** global lock list for openssl locks */
static lock_basic_t *ub_openssl_locks = NULL;
@@ -808,7 +808,7 @@ ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file),
int ub_openssl_lock_init(void)
{
-#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
+#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
int i;
ub_openssl_locks = (lock_basic_t*)reallocarray(
NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_t));
@@ -825,7 +825,7 @@ int ub_openssl_lock_init(void)
void ub_openssl_lock_delete(void)
{
-#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
+#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
int i;
if(!ub_openssl_locks)
return;
diff --git a/contrib/unbound/util/netevent.c b/contrib/unbound/util/netevent.c
index b827e65..8960b36 100644
--- a/contrib/unbound/util/netevent.c
+++ b/contrib/unbound/util/netevent.c
@@ -40,6 +40,7 @@
*/
#include "config.h"
#include "util/netevent.h"
+#include "util/ub_event.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/fptr_wlist.h"
@@ -79,8 +80,10 @@
# endif
#endif
-/** The TCP reading or writing query timeout in seconds */
-#define TCP_QUERY_TIMEOUT 120
+/** The TCP reading or writing query timeout in milliseconds */
+#define TCP_QUERY_TIMEOUT 120000
+/** The TCP timeout in msec for fast queries, above half are used */
+#define TCP_QUERY_TIMEOUT_FAST 200
#ifndef NONBLOCKING_IS_BROKEN
/** number of UDP reads to perform per read indication from select */
@@ -89,48 +92,29 @@
#define NUM_UDP_PER_SELECT 1
#endif
-/* We define libevent structures here to hide the libevent stuff. */
-
-#ifdef USE_MINI_EVENT
-# ifdef USE_WINSOCK
-# include "util/winsock_event.h"
-# else
-# include "util/mini_event.h"
-# endif /* USE_WINSOCK */
-#else /* USE_MINI_EVENT */
- /* we use libevent */
-# ifdef HAVE_EVENT_H
-# include <event.h>
-# else
-# include "event2/event.h"
-# include "event2/event_struct.h"
-# include "event2/event_compat.h"
-# endif
-#endif /* USE_MINI_EVENT */
-
/**
- * The internal event structure for keeping libevent info for the event.
+ * The internal event structure for keeping ub_event info for the event.
* Possibly other structures (list, tree) this is part of.
*/
struct internal_event {
/** the comm base */
struct comm_base* base;
- /** libevent event type, alloced here */
- struct event ev;
+ /** ub_event event type */
+ struct ub_event* ev;
};
/**
* Internal base structure, so that every thread has its own events.
*/
struct internal_base {
- /** libevent event_base type. */
- struct event_base* base;
+ /** ub_event event_base type. */
+ struct ub_event_base* base;
/** seconds time pointer points here */
time_t secs;
/** timeval with current time */
struct timeval now;
/** the event used for slow_accept timeouts */
- struct event slow_accept;
+ struct ub_event* slow_accept;
/** true if slow_accept is enabled */
int slow_accept_enabled;
};
@@ -139,10 +123,12 @@ struct internal_base {
* Internal timer structure, to store timer event in.
*/
struct internal_timer {
+ /** the super struct from which derived */
+ struct comm_timer super;
/** the comm base */
struct comm_base* base;
- /** libevent event type, alloced here */
- struct event ev;
+ /** ub_event event type */
+ struct ub_event* ev;
/** is timer enabled */
uint8_t enabled;
};
@@ -151,8 +137,8 @@ struct internal_timer {
* Internal signal structure, to store signal event in.
*/
struct internal_signal {
- /** libevent event type, alloced here */
- struct event ev;
+ /** ub_event event type */
+ struct ub_event* ev;
/** next in signal list */
struct internal_signal* next;
};
@@ -164,26 +150,13 @@ static struct comm_point* comm_point_create_tcp_handler(
/* -------- End of local definitions -------- */
-#ifdef USE_MINI_EVENT
-/** minievent updates the time when it blocks. */
-#define comm_base_now(x) /* nothing to do */
-#else /* !USE_MINI_EVENT */
-/** fillup the time values in the event base */
-static void
-comm_base_now(struct comm_base* b)
-{
- if(gettimeofday(&b->eb->now, NULL) < 0) {
- log_err("gettimeofday: %s", strerror(errno));
- }
- b->eb->secs = (time_t)b->eb->now.tv_sec;
-}
-#endif /* USE_MINI_EVENT */
-
struct comm_base*
comm_base_create(int sigs)
{
struct comm_base* b = (struct comm_base*)calloc(1,
sizeof(struct comm_base));
+ const char *evnm="event", *evsys="", *evmethod="";
+
if(!b)
return NULL;
b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base));
@@ -191,55 +164,20 @@ comm_base_create(int sigs)
free(b);
return NULL;
}
-#ifdef USE_MINI_EVENT
- (void)sigs;
- /* use mini event time-sharing feature */
- b->eb->base = event_init(&b->eb->secs, &b->eb->now);
-#else
-# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
- /* libev */
- if(sigs)
- b->eb->base=(struct event_base *)ev_default_loop(EVFLAG_AUTO);
- else
- b->eb->base=(struct event_base *)ev_loop_new(EVFLAG_AUTO);
-# else
- (void)sigs;
-# ifdef HAVE_EVENT_BASE_NEW
- b->eb->base = event_base_new();
-# else
- b->eb->base = event_init();
-# endif
-# endif
-#endif
+ b->eb->base = ub_default_event_base(sigs, &b->eb->secs, &b->eb->now);
if(!b->eb->base) {
free(b->eb);
free(b);
return NULL;
}
- comm_base_now(b);
- /* avoid event_get_method call which causes crashes even when
- * not printing, because its result is passed */
- verbose(VERB_ALGO,
-#if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
- "libev"
-#elif defined(USE_MINI_EVENT)
- "event "
-#else
- "libevent "
-#endif
- "%s uses %s method.",
- event_get_version(),
-#ifdef HAVE_EVENT_BASE_GET_METHOD
- event_base_get_method(b->eb->base)
-#else
- "not_obtainable"
-#endif
- );
+ ub_comm_base_now(b);
+ ub_get_event_sys(b->eb->base, &evnm, &evsys, &evmethod);
+ verbose(VERB_ALGO, "%s %s user %s method.", evnm, evsys, evmethod);
return b;
}
struct comm_base*
-comm_base_create_event(struct event_base* base)
+comm_base_create_event(struct ub_event_base* base)
{
struct comm_base* b = (struct comm_base*)calloc(1,
sizeof(struct comm_base));
@@ -251,7 +189,7 @@ comm_base_create_event(struct event_base* base)
return NULL;
}
b->eb->base = base;
- comm_base_now(b);
+ ub_comm_base_now(b);
return b;
}
@@ -261,18 +199,12 @@ comm_base_delete(struct comm_base* b)
if(!b)
return;
if(b->eb->slow_accept_enabled) {
- if(event_del(&b->eb->slow_accept) != 0) {
+ if(ub_event_del(b->eb->slow_accept) != 0) {
log_err("could not event_del slow_accept");
}
+ ub_event_free(b->eb->slow_accept);
}
-#ifdef USE_MINI_EVENT
- event_base_free(b->eb->base);
-#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
- /* only libevent 1.2+ has it, but in 1.2 it is broken -
- assertion fails on signal handling ev that is not deleted
- in libevent 1.3c (event_base_once appears) this is fixed. */
- event_base_free(b->eb->base);
-#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
+ ub_event_base_free(b->eb->base);
b->eb->base = NULL;
free(b->eb);
free(b);
@@ -284,9 +216,10 @@ comm_base_delete_no_base(struct comm_base* b)
if(!b)
return;
if(b->eb->slow_accept_enabled) {
- if(event_del(&b->eb->slow_accept) != 0) {
+ if(ub_event_del(b->eb->slow_accept) != 0) {
log_err("could not event_del slow_accept");
}
+ ub_event_free(b->eb->slow_accept);
}
b->eb->base = NULL;
free(b->eb);
@@ -304,8 +237,8 @@ void
comm_base_dispatch(struct comm_base* b)
{
int retval;
- retval = event_base_dispatch(b->eb->base);
- if(retval != 0) {
+ retval = ub_event_base_dispatch(b->eb->base);
+ if(retval < 0) {
fatal_exit("event_dispatch returned error %d, "
"errno is %s", retval, strerror(errno));
}
@@ -313,7 +246,7 @@ comm_base_dispatch(struct comm_base* b)
void comm_base_exit(struct comm_base* b)
{
- if(event_base_loopexit(b->eb->base, NULL) != 0) {
+ if(ub_event_base_loopexit(b->eb->base) != 0) {
log_err("Could not loopexit");
}
}
@@ -326,7 +259,7 @@ void comm_base_set_slow_accept_handlers(struct comm_base* b,
b->cb_arg = arg;
}
-struct event_base* comm_base_internal(struct comm_base* b)
+struct ub_event_base* comm_base_internal(struct comm_base* b)
{
return b->eb->base;
}
@@ -648,10 +581,10 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
- if(!(event&EV_READ))
+ if(!(event&UB_EV_READ))
return;
log_assert(rep.c && rep.c->buffer && rep.c->fd == fd);
- comm_base_now(rep.c->ev->base);
+ ub_comm_base_now(rep.c->ev->base);
for(i=0; i<NUM_UDP_PER_SELECT; i++) {
sldns_buffer_clear(rep.c->buffer);
rep.addrlen = (socklen_t)sizeof(rep.addr);
@@ -736,10 +669,10 @@ comm_point_udp_callback(int fd, short event, void* arg)
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
- if(!(event&EV_READ))
+ if(!(event&UB_EV_READ))
return;
log_assert(rep.c && rep.c->buffer && rep.c->fd == fd);
- comm_base_now(rep.c->ev->base);
+ ub_comm_base_now(rep.c->ev->base);
for(i=0; i<NUM_UDP_PER_SELECT; i++) {
sldns_buffer_clear(rep.c->buffer);
rep.addrlen = (socklen_t)sizeof(rep.addr);
@@ -779,14 +712,20 @@ comm_point_udp_callback(int fd, short event, void* arg)
/** Use a new tcp handler for new query fd, set to read query */
static void
-setup_tcp_handler(struct comm_point* c, int fd)
+setup_tcp_handler(struct comm_point* c, int fd, int cur, int max)
{
log_assert(c->type == comm_tcp);
log_assert(c->fd == -1);
sldns_buffer_clear(c->buffer);
c->tcp_is_reading = 1;
c->tcp_byte_count = 0;
- comm_point_start_listening(c, fd, TCP_QUERY_TIMEOUT);
+ c->tcp_timeout_msec = TCP_QUERY_TIMEOUT;
+ /* if more than half the tcp handlers are in use, use a shorter
+ * timeout for this TCP connection, we need to make space for
+ * other connections to be able to get attention */
+ if(cur > max/2)
+ c->tcp_timeout_msec = TCP_QUERY_TIMEOUT_FAST;
+ comm_point_start_listening(c, fd, c->tcp_timeout_msec);
}
void comm_base_handle_slow_accept(int ATTR_UNUSED(fd),
@@ -838,16 +777,17 @@ int comm_point_perform_accept(struct comm_point* c,
(*b->stop_accept)(b->cb_arg);
/* set timeout, no mallocs */
tv.tv_sec = NETEVENT_SLOW_ACCEPT_TIME/1000;
- tv.tv_usec = NETEVENT_SLOW_ACCEPT_TIME%1000;
- event_set(&b->eb->slow_accept, -1, EV_TIMEOUT,
+ tv.tv_usec = (NETEVENT_SLOW_ACCEPT_TIME%1000)*1000;
+ b->eb->slow_accept = ub_event_new(b->eb->base,
+ -1, UB_EV_TIMEOUT,
comm_base_handle_slow_accept, b);
- if(event_base_set(b->eb->base,
- &b->eb->slow_accept) != 0) {
+ if(b->eb->slow_accept == NULL) {
/* we do not want to log here, because
* that would spam the logfiles.
* error: "event_base_set failed." */
}
- if(event_add(&b->eb->slow_accept, &tv) != 0) {
+ else if(ub_event_add(b->eb->slow_accept, &tv)
+ != 0) {
/* we do not want to log here,
* error: "event_add failed." */
}
@@ -861,7 +801,7 @@ int comm_point_perform_accept(struct comm_point* c,
WSAGetLastError() == WSAECONNRESET)
return -1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
- winsock_tcp_wouldblock(&c->ev->ev, EV_READ);
+ ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
return -1;
}
log_err_addr("accept failed", wsa_strerror(WSAGetLastError()),
@@ -885,14 +825,14 @@ static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp),
if( (oper == (BIO_CB_READ|BIO_CB_RETURN) && argl == 0) ||
(oper == (BIO_CB_GETS|BIO_CB_RETURN) && argl == 0)) {
if(WSAGetLastError() == WSAEWOULDBLOCK)
- winsock_tcp_wouldblock((struct event*)
- BIO_get_callback_arg(b), EV_READ);
+ ub_winsock_tcp_wouldblock((struct ub_event*)
+ BIO_get_callback_arg(b), UB_EV_READ);
}
if( (oper == (BIO_CB_WRITE|BIO_CB_RETURN) && argl == 0) ||
(oper == (BIO_CB_PUTS|BIO_CB_RETURN) && argl == 0)) {
if(WSAGetLastError() == WSAEWOULDBLOCK)
- winsock_tcp_wouldblock((struct event*)
- BIO_get_callback_arg(b), EV_WRITE);
+ ub_winsock_tcp_wouldblock((struct ub_event*)
+ BIO_get_callback_arg(b), UB_EV_WRITE);
}
/* return original return value */
return retvalue;
@@ -905,9 +845,9 @@ comm_point_tcp_win_bio_cb(struct comm_point* c, void* thessl)
SSL* ssl = (SSL*)thessl;
/* set them both just in case, but usually they are the same BIO */
BIO_set_callback(SSL_get_rbio(ssl), &win_bio_cb);
- BIO_set_callback_arg(SSL_get_rbio(ssl), (char*)&c->ev->ev);
+ BIO_set_callback_arg(SSL_get_rbio(ssl), (char*)c->ev->ev);
BIO_set_callback(SSL_get_wbio(ssl), &win_bio_cb);
- BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)&c->ev->ev);
+ BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)c->ev->ev);
}
#endif
@@ -917,11 +857,11 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
struct comm_point* c = (struct comm_point*)arg, *c_hdl;
int new_fd;
log_assert(c->type == comm_tcp_accept);
- if(!(event & EV_READ)) {
+ if(!(event & UB_EV_READ)) {
log_info("ignoring tcp accept event %d", (int)event);
return;
}
- comm_base_now(c->ev->base);
+ ub_comm_base_now(c->ev->base);
/* find free tcp handler. */
if(!c->tcp_free) {
log_warn("accepted too many tcp, connections full");
@@ -930,6 +870,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
/* accept incoming connection. */
c_hdl = c->tcp_free;
log_assert(fd != -1);
+ (void)fd;
new_fd = comm_point_perform_accept(c, &c_hdl->repinfo.addr,
&c_hdl->repinfo.addrlen);
if(new_fd == -1)
@@ -954,7 +895,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
/* stop accepting incoming queries for now. */
comm_point_stop_listening(c);
}
- setup_tcp_handler(c_hdl, new_fd);
+ setup_tcp_handler(c_hdl, new_fd, c->cur_tcp_count, c->max_tcp_count);
}
/** Make tcp handler free for next assignment */
@@ -1008,7 +949,7 @@ tcp_callback_reader(struct comm_point* c)
comm_point_stop_listening(c);
fptr_ok(fptr_whitelist_comm_point(c->callback));
if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) {
- comm_point_start_listening(c, -1, TCP_QUERY_TIMEOUT);
+ comm_point_start_listening(c, -1, c->tcp_timeout_msec);
}
}
@@ -1297,7 +1238,8 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
if(WSAGetLastError() == WSAEINPROGRESS)
return 1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
- winsock_tcp_wouldblock(&c->ev->ev, EV_READ);
+ ub_winsock_tcp_wouldblock(c->ev->ev,
+ UB_EV_READ);
return 1;
}
log_err_addr("read (in tcp s)",
@@ -1342,7 +1284,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
if(WSAGetLastError() == WSAEINPROGRESS)
return 1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
- winsock_tcp_wouldblock(&c->ev->ev, EV_READ);
+ ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
return 1;
}
log_err_addr("read (in tcp r)",
@@ -1401,7 +1343,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if(error == WSAEINPROGRESS)
return 1;
else if(error == WSAEWOULDBLOCK) {
- winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE);
+ ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1;
} else if(error != 0 && verbosity < 2)
return 0;
@@ -1415,6 +1357,59 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if(c->ssl)
return ssl_handle_it(c);
+#ifdef USE_MSG_FASTOPEN
+ /* Only try this on first use of a connection that uses tfo,
+ otherwise fall through to normal write */
+ /* Also, TFO support on WINDOWS not implemented at the moment */
+ if(c->tcp_do_fastopen == 1) {
+ /* this form of sendmsg() does both a connect() and send() so need to
+ look for various flavours of error*/
+ uint16_t len = htons(sldns_buffer_limit(c->buffer));
+ struct msghdr msg;
+ struct iovec iov[2];
+ c->tcp_do_fastopen = 0;
+ memset(&msg, 0, sizeof(msg));
+ iov[0].iov_base = (uint8_t*)&len + c->tcp_byte_count;
+ iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count;
+ iov[1].iov_base = sldns_buffer_begin(c->buffer);
+ iov[1].iov_len = sldns_buffer_limit(c->buffer);
+ log_assert(iov[0].iov_len > 0);
+ log_assert(iov[1].iov_len > 0);
+ msg.msg_name = &c->repinfo.addr;
+ msg.msg_namelen = c->repinfo.addrlen;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 2;
+ r = sendmsg(fd, &msg, MSG_FASTOPEN);
+ if (r == -1) {
+#if defined(EINPROGRESS) && defined(EWOULDBLOCK)
+ /* Handshake is underway, maybe because no TFO cookie available.
+ Come back to write the messsage*/
+ if(errno == EINPROGRESS || errno == EWOULDBLOCK)
+ return 1;
+#endif
+ if(errno == EINTR || errno == EAGAIN)
+ return 1;
+ /* Not handling EISCONN here as shouldn't ever hit that case.*/
+ if(errno != 0 && verbosity < 2)
+ return 0; /* silence lots of chatter in the logs */
+ else if(errno != 0)
+ log_err_addr("tcp sendmsg", strerror(errno),
+ &c->repinfo.addr, c->repinfo.addrlen);
+ return 0;
+ } else {
+ c->tcp_byte_count += r;
+ if(c->tcp_byte_count < sizeof(uint16_t))
+ return 1;
+ sldns_buffer_set_position(c->buffer, c->tcp_byte_count -
+ sizeof(uint16_t));
+ if(sldns_buffer_remaining(c->buffer) == 0) {
+ tcp_callback_writer(c);
+ return 1;
+ }
+ }
+ }
+#endif /* USE_MSG_FASTOPEN */
+
if(c->tcp_byte_count < sizeof(uint16_t)) {
uint16_t len = htons(sldns_buffer_limit(c->buffer));
#ifdef HAVE_WRITEV
@@ -1451,7 +1446,8 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if(WSAGetLastError() == WSAEINPROGRESS)
return 1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
- winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE);
+ ub_winsock_tcp_wouldblock(c->ev->ev,
+ UB_EV_WRITE);
return 1;
}
log_err_addr("tcp send s",
@@ -1483,7 +1479,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if(WSAGetLastError() == WSAEINPROGRESS)
return 1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
- winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE);
+ ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1;
}
log_err_addr("tcp send r", wsa_strerror(WSAGetLastError()),
@@ -1505,9 +1501,9 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
{
struct comm_point* c = (struct comm_point*)arg;
log_assert(c->type == comm_tcp);
- comm_base_now(c->ev->base);
+ ub_comm_base_now(c->ev->base);
- if(event&EV_READ) {
+ if(event&UB_EV_READ) {
if(!comm_point_tcp_handle_read(fd, c, 0)) {
reclaim_tcp_handler(c);
if(!c->tcp_do_close) {
@@ -1519,7 +1515,7 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
}
return;
}
- if(event&EV_WRITE) {
+ if(event&UB_EV_WRITE) {
if(!comm_point_tcp_handle_write(fd, c)) {
reclaim_tcp_handler(c);
if(!c->tcp_do_close) {
@@ -1531,7 +1527,7 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
}
return;
}
- if(event&EV_TIMEOUT) {
+ if(event&UB_EV_TIMEOUT) {
verbose(VERB_QUERY, "tcp took too long, dropped");
reclaim_tcp_handler(c);
if(!c->tcp_do_close) {
@@ -1548,9 +1544,9 @@ void comm_point_local_handle_callback(int fd, short event, void* arg)
{
struct comm_point* c = (struct comm_point*)arg;
log_assert(c->type == comm_local);
- comm_base_now(c->ev->base);
+ ub_comm_base_now(c->ev->base);
- if(event&EV_READ) {
+ if(event&UB_EV_READ) {
if(!comm_point_tcp_handle_read(fd, c, 1)) {
fptr_ok(fptr_whitelist_comm_point(c->callback));
(void)(*c->callback)(c, c->cb_arg, NETEVENT_CLOSED,
@@ -1567,9 +1563,9 @@ void comm_point_raw_handle_callback(int ATTR_UNUSED(fd),
struct comm_point* c = (struct comm_point*)arg;
int err = NETEVENT_NOERROR;
log_assert(c->type == comm_raw);
- comm_base_now(c->ev->base);
+ ub_comm_base_now(c->ev->base);
- if(event&EV_TIMEOUT)
+ if(event&UB_EV_TIMEOUT)
err = NETEVENT_TIMEOUT;
fptr_ok(fptr_whitelist_comm_point_raw(c->callback));
(void)(*c->callback)(c, c->cb_arg, err, NULL);
@@ -1606,18 +1602,22 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
c->do_not_close = 0;
c->tcp_do_toggle_rw = 0;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
c->inuse = 0;
c->callback = callback;
c->cb_arg = callback_arg;
- evbits = EV_READ | EV_PERSIST;
- /* libevent stuff */
- event_set(&c->ev->ev, c->fd, evbits, comm_point_udp_callback, c);
- if(event_base_set(base->eb->base, &c->ev->ev) != 0) {
+ evbits = UB_EV_READ | UB_EV_PERSIST;
+ /* ub_event stuff */
+ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
+ comm_point_udp_callback, c);
+ if(c->ev->ev == NULL) {
log_err("could not baseset udp event");
comm_point_delete(c);
return NULL;
}
- if(fd!=-1 && event_add(&c->ev->ev, c->timeout) != 0 ) {
+ if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) {
log_err("could not add udp event");
comm_point_delete(c);
return NULL;
@@ -1658,17 +1658,21 @@ comm_point_create_udp_ancil(struct comm_base *base, int fd,
c->inuse = 0;
c->tcp_do_toggle_rw = 0;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
c->callback = callback;
c->cb_arg = callback_arg;
- evbits = EV_READ | EV_PERSIST;
- /* libevent stuff */
- event_set(&c->ev->ev, c->fd, evbits, comm_point_udp_ancil_callback, c);
- if(event_base_set(base->eb->base, &c->ev->ev) != 0) {
+ evbits = UB_EV_READ | UB_EV_PERSIST;
+ /* ub_event stuff */
+ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
+ comm_point_udp_ancil_callback, c);
+ if(c->ev->ev == NULL) {
log_err("could not baseset udp event");
comm_point_delete(c);
return NULL;
}
- if(fd!=-1 && event_add(&c->ev->ev, c->timeout) != 0 ) {
+ if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) {
log_err("could not add udp event");
comm_point_delete(c);
return NULL;
@@ -1719,16 +1723,20 @@ comm_point_create_tcp_handler(struct comm_base *base,
c->do_not_close = 0;
c->tcp_do_toggle_rw = 1;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
c->repinfo.c = c;
c->callback = callback;
c->cb_arg = callback_arg;
/* add to parent free list */
c->tcp_free = parent->tcp_free;
parent->tcp_free = c;
- /* libevent stuff */
- evbits = EV_PERSIST | EV_READ | EV_TIMEOUT;
- event_set(&c->ev->ev, c->fd, evbits, comm_point_tcp_handle_callback, c);
- if(event_base_set(base->eb->base, &c->ev->ev) != 0)
+ /* ub_event stuff */
+ evbits = UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT;
+ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
+ comm_point_tcp_handle_callback, c);
+ if(c->ev->ev == NULL)
{
log_err("could not basetset tcphdl event");
parent->tcp_free = c->tcp_free;
@@ -1778,19 +1786,25 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize,
c->do_not_close = 0;
c->tcp_do_toggle_rw = 0;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
c->callback = NULL;
c->cb_arg = NULL;
- evbits = EV_READ | EV_PERSIST;
- /* libevent stuff */
- event_set(&c->ev->ev, c->fd, evbits, comm_point_tcp_accept_callback, c);
- if(event_base_set(base->eb->base, &c->ev->ev) != 0 ||
- event_add(&c->ev->ev, c->timeout) != 0 )
- {
+ evbits = UB_EV_READ | UB_EV_PERSIST;
+ /* ub_event stuff */
+ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
+ comm_point_tcp_accept_callback, c);
+ if(c->ev->ev == NULL) {
+ log_err("could not baseset tcpacc event");
+ comm_point_delete(c);
+ return NULL;
+ }
+ if (ub_event_add(c->ev->ev, c->timeout) != 0) {
log_err("could not add tcpacc event");
comm_point_delete(c);
return NULL;
}
-
/* now prealloc the tcp handlers */
for(i=0; i<num; i++) {
c->tcp_handlers[i] = comm_point_create_tcp_handler(base,
@@ -1840,14 +1854,18 @@ comm_point_create_tcp_out(struct comm_base *base, size_t bufsize,
c->do_not_close = 0;
c->tcp_do_toggle_rw = 1;
c->tcp_check_nb_connect = 1;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 1;
+#endif
c->repinfo.c = c;
c->callback = callback;
c->cb_arg = callback_arg;
- evbits = EV_PERSIST | EV_WRITE;
- event_set(&c->ev->ev, c->fd, evbits, comm_point_tcp_handle_callback, c);
- if(event_base_set(base->eb->base, &c->ev->ev) != 0)
+ evbits = UB_EV_PERSIST | UB_EV_WRITE;
+ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
+ comm_point_tcp_handle_callback, c);
+ if(c->ev->ev == NULL)
{
- log_err("could not basetset tcpout event");
+ log_err("could not baseset tcpout event");
sldns_buffer_free(c->buffer);
free(c->ev);
free(c);
@@ -1893,16 +1911,24 @@ comm_point_create_local(struct comm_base *base, int fd, size_t bufsize,
c->do_not_close = 1;
c->tcp_do_toggle_rw = 0;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
c->callback = callback;
c->cb_arg = callback_arg;
- /* libevent stuff */
- evbits = EV_PERSIST | EV_READ;
- event_set(&c->ev->ev, c->fd, evbits, comm_point_local_handle_callback,
- c);
- if(event_base_set(base->eb->base, &c->ev->ev) != 0 ||
- event_add(&c->ev->ev, c->timeout) != 0 )
- {
+ /* ub_event stuff */
+ evbits = UB_EV_PERSIST | UB_EV_READ;
+ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
+ comm_point_local_handle_callback, c);
+ if(c->ev->ev == NULL) {
+ log_err("could not baseset localhdl event");
+ free(c->ev);
+ free(c);
+ return NULL;
+ }
+ if (ub_event_add(c->ev->ev, c->timeout) != 0) {
log_err("could not add localhdl event");
+ ub_event_free(c->ev->ev);
free(c->ev);
free(c);
return NULL;
@@ -1941,18 +1967,26 @@ comm_point_create_raw(struct comm_base* base, int fd, int writing,
c->do_not_close = 1;
c->tcp_do_toggle_rw = 0;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
c->callback = callback;
c->cb_arg = callback_arg;
- /* libevent stuff */
+ /* ub_event stuff */
if(writing)
- evbits = EV_PERSIST | EV_WRITE;
- else evbits = EV_PERSIST | EV_READ;
- event_set(&c->ev->ev, c->fd, evbits, comm_point_raw_handle_callback,
- c);
- if(event_base_set(base->eb->base, &c->ev->ev) != 0 ||
- event_add(&c->ev->ev, c->timeout) != 0 )
- {
+ evbits = UB_EV_PERSIST | UB_EV_WRITE;
+ else evbits = UB_EV_PERSIST | UB_EV_READ;
+ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
+ comm_point_raw_handle_callback, c);
+ if(c->ev->ev == NULL) {
+ log_err("could not baseset rawhdl event");
+ free(c->ev);
+ free(c);
+ return NULL;
+ }
+ if (ub_event_add(c->ev->ev, c->timeout) != 0) {
log_err("could not add rawhdl event");
+ ub_event_free(c->ev->ev);
free(c->ev);
free(c);
return NULL;
@@ -1966,7 +2000,7 @@ comm_point_close(struct comm_point* c)
if(!c)
return;
if(c->fd != -1)
- if(event_del(&c->ev->ev) != 0) {
+ if(ub_event_del(c->ev->ev) != 0) {
log_err("could not event_del on close");
}
/* close fd after removing from event lists, or epoll.. is messed up */
@@ -2002,6 +2036,7 @@ comm_point_delete(struct comm_point* c)
free(c->timeout);
if(c->type == comm_tcp || c->type == comm_local)
sldns_buffer_free(c->buffer);
+ ub_event_free(c->ev->ev);
free(c->ev);
free(c);
}
@@ -2031,7 +2066,8 @@ comm_point_send_reply(struct comm_reply *repinfo)
dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv,
&repinfo->addr, repinfo->c->type, repinfo->c->buffer);
#endif
- comm_point_start_listening(repinfo->c, -1, TCP_QUERY_TIMEOUT);
+ comm_point_start_listening(repinfo->c, -1,
+ repinfo->c->tcp_timeout_msec);
}
}
@@ -2051,13 +2087,13 @@ void
comm_point_stop_listening(struct comm_point* c)
{
verbose(VERB_ALGO, "comm point stop listening %d", c->fd);
- if(event_del(&c->ev->ev) != 0) {
+ if(ub_event_del(c->ev->ev) != 0) {
log_err("event_del error to stoplisten");
}
}
void
-comm_point_start_listening(struct comm_point* c, int newfd, int sec)
+comm_point_start_listening(struct comm_point* c, int newfd, int msec)
{
verbose(VERB_ALGO, "comm point start listening %d",
c->fd==-1?newfd:c->fd);
@@ -2065,7 +2101,7 @@ comm_point_start_listening(struct comm_point* c, int newfd, int sec)
/* no use to start listening no free slots. */
return;
}
- if(sec != -1 && sec != 0) {
+ if(msec != -1 && msec != 0) {
if(!c->timeout) {
c->timeout = (struct timeval*)malloc(sizeof(
struct timeval));
@@ -2074,17 +2110,17 @@ comm_point_start_listening(struct comm_point* c, int newfd, int sec)
return;
}
}
- c->ev->ev.ev_events |= EV_TIMEOUT;
+ ub_event_add_bits(c->ev->ev, UB_EV_TIMEOUT);
#ifndef S_SPLINT_S /* splint fails on struct timeval. */
- c->timeout->tv_sec = sec;
- c->timeout->tv_usec = 0;
+ c->timeout->tv_sec = msec/1000;
+ c->timeout->tv_usec = (msec%1000)*1000;
#endif /* S_SPLINT_S */
}
if(c->type == comm_tcp) {
- c->ev->ev.ev_events &= ~(EV_READ|EV_WRITE);
+ ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE);
if(c->tcp_is_reading)
- c->ev->ev.ev_events |= EV_READ;
- else c->ev->ev.ev_events |= EV_WRITE;
+ ub_event_add_bits(c->ev->ev, UB_EV_READ);
+ else ub_event_add_bits(c->ev->ev, UB_EV_WRITE);
}
if(newfd != -1) {
if(c->fd != -1) {
@@ -2095,9 +2131,9 @@ comm_point_start_listening(struct comm_point* c, int newfd, int sec)
#endif
}
c->fd = newfd;
- c->ev->ev.ev_fd = c->fd;
+ ub_event_set_fd(c->ev->ev, c->fd);
}
- if(event_add(&c->ev->ev, sec==0?NULL:c->timeout) != 0) {
+ if(ub_event_add(c->ev->ev, msec==0?NULL:c->timeout) != 0) {
log_err("event_add failed. in cpsl.");
}
}
@@ -2105,13 +2141,13 @@ comm_point_start_listening(struct comm_point* c, int newfd, int sec)
void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr)
{
verbose(VERB_ALGO, "comm point listen_for_rw %d %d", c->fd, wr);
- if(event_del(&c->ev->ev) != 0) {
+ if(ub_event_del(c->ev->ev) != 0) {
log_err("event_del error to cplf");
}
- c->ev->ev.ev_events &= ~(EV_READ|EV_WRITE);
- if(rd) c->ev->ev.ev_events |= EV_READ;
- if(wr) c->ev->ev.ev_events |= EV_WRITE;
- if(event_add(&c->ev->ev, c->timeout) != 0) {
+ ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE);
+ if(rd) ub_event_add_bits(c->ev->ev, UB_EV_READ);
+ if(wr) ub_event_add_bits(c->ev->ev, UB_EV_WRITE);
+ if(ub_event_add(c->ev->ev, c->timeout) != 0) {
log_err("event_add failed. in cplf.");
}
}
@@ -2137,29 +2173,24 @@ size_t comm_point_get_mem(struct comm_point* c)
struct comm_timer*
comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg)
{
- struct comm_timer *tm = (struct comm_timer*)calloc(1,
- sizeof(struct comm_timer));
- if(!tm)
- return NULL;
- tm->ev_timer = (struct internal_timer*)calloc(1,
+ struct internal_timer *tm = (struct internal_timer*)calloc(1,
sizeof(struct internal_timer));
- if(!tm->ev_timer) {
+ if(!tm) {
log_err("malloc failed");
- free(tm);
return NULL;
}
- tm->ev_timer->base = base;
- tm->callback = cb;
- tm->cb_arg = cb_arg;
- event_set(&tm->ev_timer->ev, -1, EV_TIMEOUT,
- comm_timer_callback, tm);
- if(event_base_set(base->eb->base, &tm->ev_timer->ev) != 0) {
+ tm->super.ev_timer = tm;
+ tm->base = base;
+ tm->super.callback = cb;
+ tm->super.cb_arg = cb_arg;
+ tm->ev = ub_event_new(base->eb->base, -1, UB_EV_TIMEOUT,
+ comm_timer_callback, &tm->super);
+ if(tm->ev == NULL) {
log_err("timer_create: event_base_set failed.");
- free(tm->ev_timer);
free(tm);
return NULL;
}
- return tm;
+ return &tm->super;
}
void
@@ -2167,7 +2198,7 @@ comm_timer_disable(struct comm_timer* timer)
{
if(!timer)
return;
- evtimer_del(&timer->ev_timer->ev);
+ ub_timer_del(timer->ev_timer->ev);
timer->ev_timer->enabled = 0;
}
@@ -2177,12 +2208,8 @@ comm_timer_set(struct comm_timer* timer, struct timeval* tv)
log_assert(tv);
if(timer->ev_timer->enabled)
comm_timer_disable(timer);
- event_set(&timer->ev_timer->ev, -1, EV_TIMEOUT,
- comm_timer_callback, timer);
- if(event_base_set(timer->ev_timer->base->eb->base,
- &timer->ev_timer->ev) != 0)
- log_err("comm_timer_set: set_base failed.");
- if(evtimer_add(&timer->ev_timer->ev, tv) != 0)
+ if(ub_timer_add(timer->ev_timer->ev, timer->ev_timer->base->eb->base,
+ comm_timer_callback, timer, tv) != 0)
log_err("comm_timer_set: evtimer_add failed.");
timer->ev_timer->enabled = 1;
}
@@ -2193,17 +2220,20 @@ comm_timer_delete(struct comm_timer* timer)
if(!timer)
return;
comm_timer_disable(timer);
+ /* Free the sub struct timer->ev_timer derived from the super struct timer.
+ * i.e. assert(timer == timer->ev_timer)
+ */
+ ub_event_free(timer->ev_timer->ev);
free(timer->ev_timer);
- free(timer);
}
void
comm_timer_callback(int ATTR_UNUSED(fd), short event, void* arg)
{
struct comm_timer* tm = (struct comm_timer*)arg;
- if(!(event&EV_TIMEOUT))
+ if(!(event&UB_EV_TIMEOUT))
return;
- comm_base_now(tm->ev_timer->base);
+ ub_comm_base_now(tm->ev_timer->base);
tm->ev_timer->enabled = 0;
fptr_ok(fptr_whitelist_comm_timer(tm->callback));
(*tm->callback)(tm->cb_arg);
@@ -2216,9 +2246,9 @@ comm_timer_is_set(struct comm_timer* timer)
}
size_t
-comm_timer_get_mem(struct comm_timer* timer)
+comm_timer_get_mem(struct comm_timer* ATTR_UNUSED(timer))
{
- return sizeof(*timer) + sizeof(struct internal_timer);
+ return sizeof(struct internal_timer);
}
struct comm_signal*
@@ -2242,9 +2272,9 @@ void
comm_signal_callback(int sig, short event, void* arg)
{
struct comm_signal* comsig = (struct comm_signal*)arg;
- if(!(event & EV_SIGNAL))
+ if(!(event & UB_EV_SIGNAL))
return;
- comm_base_now(comsig->base);
+ ub_comm_base_now(comsig->base);
fptr_ok(fptr_whitelist_comm_signal(comsig->callback));
(*comsig->callback)(sig, comsig->cb_arg);
}
@@ -2260,14 +2290,16 @@ comm_signal_bind(struct comm_signal* comsig, int sig)
}
log_assert(comsig);
/* add signal event */
- signal_set(&entry->ev, sig, comm_signal_callback, comsig);
- if(event_base_set(comsig->base->eb->base, &entry->ev) != 0) {
- log_err("Could not set signal base");
+ entry->ev = ub_signal_new(comsig->base->eb->base, sig,
+ comm_signal_callback, comsig);
+ if(entry->ev == NULL) {
+ log_err("Could not create signal event");
free(entry);
return 0;
}
- if(signal_add(&entry->ev, NULL) != 0) {
+ if(ub_signal_add(entry->ev, NULL) != 0) {
log_err("Could not add signal handler");
+ ub_event_free(entry->ev);
free(entry);
return 0;
}
@@ -2286,7 +2318,8 @@ comm_signal_delete(struct comm_signal* comsig)
p=comsig->ev_signal;
while(p) {
np = p->next;
- signal_del(&p->ev);
+ ub_signal_del(p->ev);
+ ub_event_free(p->ev);
free(p);
p = np;
}
diff --git a/contrib/unbound/util/netevent.h b/contrib/unbound/util/netevent.h
index 4b87cdb..1d7ac0b 100644
--- a/contrib/unbound/util/netevent.h
+++ b/contrib/unbound/util/netevent.h
@@ -63,12 +63,12 @@
struct sldns_buffer;
struct comm_point;
struct comm_reply;
-struct event_base;
+struct ub_event_base;
/* internal event notification data storage structure. */
struct internal_event;
struct internal_base;
-struct internal_timer;
+struct internal_timer; /* A sub struct of the comm_timer super struct */
/** callback from communication point function type */
typedef int comm_point_callback_t(struct comm_point*, void*, int,
@@ -225,9 +225,17 @@ struct comm_point {
So that when that is done the callback is called. */
int tcp_do_toggle_rw;
+ /** timeout in msec for TCP wait times for this connection */
+ int tcp_timeout_msec;
+
/** if set, checks for pending error from nonblocking connect() call.*/
int tcp_check_nb_connect;
+#ifdef USE_MSG_FASTOPEN
+ /** used to track if the sendto() call should be done when using TFO. */
+ int tcp_do_fastopen;
+#endif
+
/** number of queries outstanding on this socket, used by
* outside network for udp ports */
int inuse;
@@ -265,7 +273,7 @@ struct comm_point {
* Structure only for making timeout events.
*/
struct comm_timer {
- /** the internal event stuff */
+ /** the internal event stuff (derived) */
struct internal_timer* ev_timer;
/** callback function, takes user arg only */
@@ -301,12 +309,12 @@ struct comm_signal {
struct comm_base* comm_base_create(int sigs);
/**
- * Create comm base that uses the given event_base (underlying event
- * mechanism pointer).
- * @param base: underlying lib event base.
+ * Create comm base that uses the given ub_event_base (underlying pluggable
+ * event mechanism pointer).
+ * @param base: underlying pluggable event base.
* @return: the new comm base. NULL on error.
*/
-struct comm_base* comm_base_create_event(struct event_base* base);
+struct comm_base* comm_base_create_event(struct ub_event_base* base);
/**
* Delete comm base structure but not the underlying lib event base.
@@ -357,9 +365,9 @@ void comm_base_set_slow_accept_handlers(struct comm_base* b,
/**
* Access internal data structure (for util/tube.c on windows)
* @param b: comm base
- * @return event_base. Could be libevent, or internal event handler.
+ * @return ub_event_base.
*/
-struct event_base* comm_base_internal(struct comm_base* b);
+struct ub_event_base* comm_base_internal(struct comm_base* b);
/**
* Create an UDP comm point. Calls malloc.
@@ -496,9 +504,10 @@ void comm_point_stop_listening(struct comm_point* c);
* Start listening again for input on the comm point.
* @param c: commpoint to enable again.
* @param newfd: new fd, or -1 to leave fd be.
- * @param sec: timeout in seconds, or -1 for no (change to the) timeout.
+ * @param msec: timeout in milliseconds, or -1 for no (change to the) timeout.
+ * So seconds*1000.
*/
-void comm_point_start_listening(struct comm_point* c, int newfd, int sec);
+void comm_point_start_listening(struct comm_point* c, int newfd, int msec);
/**
* Stop listening and start listening again for reading or writing.
diff --git a/contrib/unbound/util/storage/dnstree.c b/contrib/unbound/util/storage/dnstree.c
index 0df490e..7664c47 100644
--- a/contrib/unbound/util/storage/dnstree.c
+++ b/contrib/unbound/util/storage/dnstree.c
@@ -231,6 +231,19 @@ struct addr_tree_node* addr_tree_lookup(rbtree_t* tree,
return result;
}
+struct addr_tree_node* addr_tree_find(rbtree_t* tree,
+ struct sockaddr_storage* addr, socklen_t addrlen, int net)
+{
+ rbnode_t* res = NULL;
+ struct addr_tree_node key;
+ key.node.key = &key;
+ memcpy(&key.addr, addr, addrlen);
+ key.addrlen = addrlen;
+ key.net = net;
+ res = rbtree_search(tree, &key);
+ return (struct addr_tree_node*)res;
+}
+
int
name_tree_next_root(rbtree_t* tree, uint16_t* dclass)
{
diff --git a/contrib/unbound/util/storage/dnstree.h b/contrib/unbound/util/storage/dnstree.h
index ec81891..b4595e1 100644
--- a/contrib/unbound/util/storage/dnstree.h
+++ b/contrib/unbound/util/storage/dnstree.h
@@ -183,6 +183,17 @@ void addr_tree_init_parents(rbtree_t* tree);
struct addr_tree_node* addr_tree_lookup(rbtree_t* tree,
struct sockaddr_storage* addr, socklen_t addrlen);
+/**
+ * Find element in addr tree. (search a netblock, not a match for an address)
+ * @param tree: addr tree
+ * @param addr: netblock to lookup.
+ * @param addrlen: length of addr
+ * @param net: size of subnet
+ * @return addr tree element, or NULL if not found.
+ */
+struct addr_tree_node* addr_tree_find(rbtree_t* tree,
+ struct sockaddr_storage* addr, socklen_t addrlen, int net);
+
/** compare name tree nodes */
int name_tree_compare(const void* k1, const void* k2);
diff --git a/contrib/unbound/util/storage/lookup3.c b/contrib/unbound/util/storage/lookup3.c
index ddcb56e..e9b05af 100644
--- a/contrib/unbound/util/storage/lookup3.c
+++ b/contrib/unbound/util/storage/lookup3.c
@@ -820,7 +820,7 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval)
#ifdef SELF_TEST
/* used for timings */
-void driver1()
+void driver1(void)
{
uint8_t buf[256];
uint32_t i;
@@ -842,7 +842,7 @@ void driver1()
#define HASHLEN 1
#define MAXPAIR 60
#define MAXLEN 70
-void driver2()
+void driver2(void)
{
uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z;
@@ -912,7 +912,7 @@ void driver2()
}
/* Check for reading beyond the end of the buffer and alignment problems */
-void driver3()
+void driver3(void)
{
uint8_t buf[MAXLEN+20], *b;
uint32_t len;
@@ -1003,7 +1003,7 @@ void driver3()
}
/* check for problems with nulls */
- void driver4()
+ void driver4(void)
{
uint8_t buf[1];
uint32_t h,i,state[HASHSTATE];
@@ -1020,7 +1020,7 @@ void driver3()
}
-int main()
+int main(void)
{
driver1(); /* test that the key is hashed: used for timings */
driver2(); /* test that whole key is hashed thoroughly */
diff --git a/contrib/unbound/util/tube.c b/contrib/unbound/util/tube.c
index 0535474..e525f1c 100644
--- a/contrib/unbound/util/tube.c
+++ b/contrib/unbound/util/tube.c
@@ -44,6 +44,7 @@
#include "util/net_help.h"
#include "util/netevent.h"
#include "util/fptr_wlist.h"
+#include "util/ub_event.h"
#ifndef USE_WINSOCK
/* on unix */
@@ -303,6 +304,8 @@ int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len,
d = r;
while(d != (ssize_t)sizeof(len)) {
if((r=write(fd, ((char*)&len)+d, sizeof(len)-d)) == -1) {
+ if(errno == EAGAIN)
+ continue; /* temporarily unavail: try again*/
log_err("tube msg write failed: %s", strerror(errno));
(void)fd_set_nonblock(fd);
return 0;
@@ -312,6 +315,8 @@ int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len,
d = 0;
while(d != (ssize_t)len) {
if((r=write(fd, buf+d, len-d)) == -1) {
+ if(errno == EAGAIN)
+ continue; /* temporarily unavail: try again*/
log_err("tube msg write failed: %s", strerror(errno));
(void)fd_set_nonblock(fd);
return 0;
@@ -537,7 +542,7 @@ void tube_close_write(struct tube* ATTR_UNUSED(tube))
void tube_remove_bg_listen(struct tube* tube)
{
verbose(VERB_ALGO, "tube remove_bg_listen");
- winsock_unregister_wsaevent(&tube->ev_listen);
+ ub_winsock_unregister_wsaevent(tube->ev_listen);
}
void tube_remove_bg_write(struct tube* tube)
@@ -668,8 +673,9 @@ int tube_setup_bg_listen(struct tube* tube, struct comm_base* base,
tube->listen_arg = arg;
if(!comm_base_internal(base))
return 1; /* ignore when no comm base - testing */
- return winsock_register_wsaevent(comm_base_internal(base),
- &tube->ev_listen, tube->event, &tube_handle_signal, tube);
+ tube->ev_listen = ub_winsock_register_wsaevent(
+ comm_base_internal(base), tube->event, &tube_handle_signal, tube);
+ return tube->ev_listen ? 1 : 0;
}
int tube_setup_bg_write(struct tube* ATTR_UNUSED(tube),
diff --git a/contrib/unbound/util/tube.h b/contrib/unbound/util/tube.h
index 6cc6050..7971b77 100644
--- a/contrib/unbound/util/tube.h
+++ b/contrib/unbound/util/tube.h
@@ -48,7 +48,6 @@ struct tube;
struct tube_res_list;
#ifdef USE_WINSOCK
#include "util/locks.h"
-#include "util/winsock_event.h"
#endif
/**
@@ -99,7 +98,7 @@ struct tube {
/** the windows sockets event (signaled if items in pipe) */
WSAEVENT event;
/** winsock event storage when registered with event base */
- struct event ev_listen;
+ struct ub_event* ev_listen;
/** lock on the list of outstanding items */
lock_basic_t res_lock;
diff --git a/contrib/unbound/util/ub_event.c b/contrib/unbound/util/ub_event.c
new file mode 100644
index 0000000..3b92be1
--- /dev/null
+++ b/contrib/unbound/util/ub_event.c
@@ -0,0 +1,444 @@
+/*
+ * util/ub_event.c - directly call libevent (compatability) functions
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * 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 of the NLNET LABS 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
+ * HOLDER 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.
+ */
+
+/**
+ * \file
+ *
+ * This file contains and implementation for the indirection layer for pluggable
+ * events that transparently passes it either directly to libevent, or calls
+ * the libevent compatibility layer functions.
+ */
+#include "config.h"
+#include <sys/time.h>
+#include "util/ub_event.h"
+#include "util/log.h"
+#include "util/netevent.h"
+#include "util/tube.h"
+
+/* We define libevent structures here to hide the libevent stuff. */
+
+#ifdef USE_MINI_EVENT
+# ifdef USE_WINSOCK
+# include "util/winsock_event.h"
+# else
+# include "util/mini_event.h"
+# endif /* USE_WINSOCK */
+#else /* USE_MINI_EVENT */
+ /* we use libevent */
+# ifdef HAVE_EVENT_H
+# include <event.h>
+# else
+# include "event2/event.h"
+# include "event2/event_struct.h"
+# include "event2/event_compat.h"
+# endif
+#endif /* USE_MINI_EVENT */
+
+#if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \
+ UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \
+ UB_EV_PERSIST != EV_PERSIST
+/* Only necessary for libev */
+# define NATIVE_BITS(b) ( \
+ (((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \
+ | (((b) & UB_EV_READ ) ? EV_READ : 0) \
+ | (((b) & UB_EV_WRITE ) ? EV_WRITE : 0) \
+ | (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL : 0) \
+ | (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0))
+
+# define UB_EV_BITS(b) ( \
+ (((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \
+ | (((b) & EV_READ ) ? UB_EV_READ : 0) \
+ | (((b) & EV_WRITE ) ? UB_EV_WRITE : 0) \
+ | (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL : 0) \
+ | (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0))
+
+# define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \
+ { (C)(fd, UB_EV_BITS(bits), arg); }
+
+UB_EV_BITS_CB(comm_point_udp_callback);
+UB_EV_BITS_CB(comm_point_udp_ancil_callback)
+UB_EV_BITS_CB(comm_point_tcp_accept_callback)
+UB_EV_BITS_CB(comm_point_tcp_handle_callback)
+UB_EV_BITS_CB(comm_timer_callback)
+UB_EV_BITS_CB(comm_signal_callback)
+UB_EV_BITS_CB(comm_point_local_handle_callback)
+UB_EV_BITS_CB(comm_point_raw_handle_callback)
+UB_EV_BITS_CB(tube_handle_signal)
+UB_EV_BITS_CB(comm_base_handle_slow_accept)
+
+static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
+{
+ if(cb == comm_point_udp_callback)
+ return my_comm_point_udp_callback;
+ else if(cb == comm_point_udp_ancil_callback)
+ return my_comm_point_udp_ancil_callback;
+ else if(cb == comm_point_tcp_accept_callback)
+ return my_comm_point_tcp_accept_callback;
+ else if(cb == comm_point_tcp_handle_callback)
+ return my_comm_point_tcp_handle_callback;
+ else if(cb == comm_timer_callback)
+ return my_comm_timer_callback;
+ else if(cb == comm_signal_callback)
+ return my_comm_signal_callback;
+ else if(cb == comm_point_local_handle_callback)
+ return my_comm_point_local_handle_callback;
+ else if(cb == comm_point_raw_handle_callback)
+ return my_comm_point_raw_handle_callback;
+ else if(cb == tube_handle_signal)
+ return my_tube_handle_signal;
+ else if(cb == comm_base_handle_slow_accept)
+ return my_comm_base_handle_slow_accept;
+ else
+ return NULL;
+}
+#else
+# define NATIVE_BITS(b) (b)
+# define NATIVE_BITS_CB(c) (c)
+#endif
+
+#ifndef EVFLAG_AUTO
+#define EVFLAG_AUTO 0
+#endif
+
+#define AS_EVENT_BASE(x) ((struct event_base*)x)
+#define AS_UB_EVENT_BASE(x) ((struct ub_event_base*)x)
+#define AS_EVENT(x) ((struct event*)x)
+#define AS_UB_EVENT(x) ((struct ub_event*)x)
+
+const char* ub_event_get_version(void)
+{
+ return event_get_version();
+}
+
+#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
+static const char* ub_ev_backend2str(int b)
+{
+ switch(b) {
+ case EVBACKEND_SELECT: return "select";
+ case EVBACKEND_POLL: return "poll";
+ case EVBACKEND_EPOLL: return "epoll";
+ case EVBACKEND_KQUEUE: return "kqueue";
+ case EVBACKEND_DEVPOLL: return "devpoll";
+ case EVBACKEND_PORT: return "evport";
+ }
+ return "unknown";
+}
+#endif
+
+void
+ub_get_event_sys(struct ub_event_base* base, const char** n, const char** s,
+ const char** m)
+{
+#ifdef USE_WINSOCK
+ (void)base;
+ *n = "event";
+ *s = "winsock";
+ *m = "WSAWaitForMultipleEvents";
+#elif defined(USE_MINI_EVENT)
+ (void)base;
+ *n = "mini-event";
+ *s = "internal";
+ *m = "select";
+#else
+ struct event_base* b = AS_EVENT_BASE(base);
+ *s = event_get_version();
+# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
+ *n = "libev";
+ if (!b)
+ b = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
+# ifdef EVBACKEND_SELECT
+ *m = ub_ev_backend2str(ev_backend((struct ev_loop*)b));
+# else
+ *m = "not obtainable";
+# endif
+# elif defined(HAVE_EVENT_BASE_GET_METHOD)
+ *n = "libevent";
+ if (!b)
+ b = event_base_new();
+ *m = event_base_get_method(b);
+# else
+ *n = "unknown";
+ *m = "not obtainable";
+ (void)b;
+# endif
+# ifdef HAVE_EVENT_BASE_FREE
+ if (b && b != AS_EVENT_BASE(base))
+ event_base_free(b);
+# endif
+#endif
+}
+
+struct ub_event_base*
+ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv)
+{
+ void* base;
+
+ (void)base;
+#ifdef USE_MINI_EVENT
+ (void)sigs;
+ /* use mini event time-sharing feature */
+ base = event_init(time_secs, time_tv);
+#else
+ (void)time_secs;
+ (void)time_tv;
+# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
+ /* libev */
+ if(sigs)
+ base = ev_default_loop(EVFLAG_AUTO);
+ else
+ base = ev_loop_new(EVFLAG_AUTO);
+# else
+ (void)sigs;
+# ifdef HAVE_EVENT_BASE_NEW
+ base = event_base_new();
+# else
+ base = event_init();
+# endif
+# endif
+#endif
+ return (struct ub_event_base*)base;
+}
+
+struct ub_event_base *
+ub_libevent_event_base(struct event_base* libevent_base)
+{
+#ifdef USE_MINI_EVENT
+ (void)libevent_base;
+ return NULL;
+#else
+ return AS_UB_EVENT_BASE(libevent_base);
+#endif
+}
+
+struct event_base *
+ub_libevent_get_event_base(struct ub_event_base* base)
+{
+#ifdef USE_MINI_EVENT
+ (void)base;
+ return NULL;
+#else
+ return AS_EVENT_BASE(base);
+#endif
+}
+
+void
+ub_event_base_free(struct ub_event_base* base)
+{
+#ifdef USE_MINI_EVENT
+ event_base_free(AS_EVENT_BASE(base));
+#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
+ /* only libevent 1.2+ has it, but in 1.2 it is broken -
+ assertion fails on signal handling ev that is not deleted
+ in libevent 1.3c (event_base_once appears) this is fixed. */
+ event_base_free(AS_EVENT_BASE(base));
+#else
+ (void)base;
+#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
+}
+
+int
+ub_event_base_dispatch(struct ub_event_base* base)
+{
+ return event_base_dispatch(AS_EVENT_BASE(base));
+}
+
+int
+ub_event_base_loopexit(struct ub_event_base* base)
+{
+ return event_base_loopexit(AS_EVENT_BASE(base), NULL);
+}
+
+struct ub_event*
+ub_event_new(struct ub_event_base* base, int fd, short bits,
+ void (*cb)(int, short, void*), void* arg)
+{
+ struct event *ev = (struct event*)calloc(1, sizeof(struct event));
+
+ if (!ev)
+ return NULL;
+
+ event_set(ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
+ if (event_base_set(AS_EVENT_BASE(base), ev) != 0) {
+ free(ev);
+ return NULL;
+ }
+ return AS_UB_EVENT(ev);
+}
+
+struct ub_event*
+ub_signal_new(struct ub_event_base* base, int fd,
+ void (*cb)(int, short, void*), void* arg)
+{
+ struct event *ev = (struct event*)calloc(1, sizeof(struct event));
+
+ if (!ev)
+ return NULL;
+
+ signal_set(ev, fd, NATIVE_BITS_CB(cb), arg);
+ if (event_base_set(AS_EVENT_BASE(base), ev) != 0) {
+ free(ev);
+ return NULL;
+ }
+ return AS_UB_EVENT(ev);
+}
+
+struct ub_event*
+ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
+ void (*cb)(int, short, void*), void* arg)
+{
+#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
+ struct event *ev = (struct event*)calloc(1, sizeof(struct event));
+
+ if (!ev)
+ return NULL;
+
+ if (winsock_register_wsaevent(AS_EVENT_BASE(base), ev, wsaevent, cb,
+ arg))
+ return AS_UB_EVENT(ev);
+ free(ev);
+ return NULL;
+#else
+ (void)base;
+ (void)wsaevent;
+ (void)cb;
+ (void)arg;
+ return NULL;
+#endif
+}
+
+void
+ub_event_add_bits(struct ub_event* ev, short bits)
+{
+ AS_EVENT(ev)->ev_events |= NATIVE_BITS(bits);
+}
+
+void
+ub_event_del_bits(struct ub_event* ev, short bits)
+{
+ AS_EVENT(ev)->ev_events &= ~NATIVE_BITS(bits);
+}
+
+void
+ub_event_set_fd(struct ub_event* ev, int fd)
+{
+ AS_EVENT(ev)->ev_fd = fd;
+}
+
+void
+ub_event_free(struct ub_event* ev)
+{
+ if (ev)
+ free(AS_EVENT(ev));
+}
+
+int
+ub_event_add(struct ub_event* ev, struct timeval* tv)
+{
+ return event_add(AS_EVENT(ev), tv);
+}
+
+int
+ub_event_del(struct ub_event* ev)
+{
+ return event_del(AS_EVENT(ev));
+}
+
+int
+ub_timer_add(struct ub_event* ev, struct ub_event_base* base,
+ void (*cb)(int, short, void*), void* arg, struct timeval* tv)
+{
+ event_set(AS_EVENT(ev), -1, EV_TIMEOUT, NATIVE_BITS_CB(cb), arg);
+ if (event_base_set(AS_EVENT_BASE(base), AS_EVENT(ev)) != 0)
+ return -1;
+ return evtimer_add(AS_EVENT(ev), tv);
+}
+
+int
+ub_timer_del(struct ub_event* ev)
+{
+ return evtimer_del(AS_EVENT(ev));
+}
+
+int
+ub_signal_add(struct ub_event* ev, struct timeval* tv)
+{
+ return signal_add(AS_EVENT(ev), tv);
+}
+
+int
+ub_signal_del(struct ub_event* ev)
+{
+ return signal_del(AS_EVENT(ev));
+}
+
+void
+ub_winsock_unregister_wsaevent(struct ub_event* ev)
+{
+#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
+ winsock_unregister_wsaevent(AS_EVENT(ev));
+ free(AS_EVENT(ev));
+#else
+ (void)ev;
+#endif
+}
+
+void
+ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
+{
+#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
+ winsock_tcp_wouldblock(AS_EVENT(ev), NATIVE_BITS(eventbits));
+#else
+ (void)ev;
+ (void)eventbits;
+#endif
+}
+
+void ub_comm_base_now(struct comm_base* cb)
+{
+ #ifdef USE_MINI_EVENT
+/** minievent updates the time when it blocks. */
+ (void)cb; /* nothing to do */
+#else /* !USE_MINI_EVENT */
+/** fillup the time values in the event base */
+ time_t *tt;
+ struct timeval *tv;
+ comm_base_timept(cb, &tt, &tv);
+ if(gettimeofday(tv, NULL) < 0) {
+ log_err("gettimeofday: %s", strerror(errno));
+ }
+ *tt = tv->tv_sec;
+#endif /* USE_MINI_EVENT */
+}
+
diff --git a/contrib/unbound/util/ub_event.h b/contrib/unbound/util/ub_event.h
new file mode 100644
index 0000000..9739e6d
--- /dev/null
+++ b/contrib/unbound/util/ub_event.h
@@ -0,0 +1,127 @@
+/*
+ * util/ub_event.h - indirection layer for pluggable events
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * 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 of the NLNET LABS 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
+ * HOLDER 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.
+ */
+
+/**
+ * \file
+ *
+ * This file contains prototypes for event loop functions.
+ *
+ */
+
+#ifndef UB_EVENT_H
+#define UB_EVENT_H
+
+struct ub_event_base;
+struct ub_event;
+struct comm_base;
+struct event_base;
+
+/** event timeout */
+#define UB_EV_TIMEOUT 0x01
+/** event fd readable */
+#define UB_EV_READ 0x02
+/** event fd writable */
+#define UB_EV_WRITE 0x04
+/** event signal */
+#define UB_EV_SIGNAL 0x08
+/** event must persist */
+#define UB_EV_PERSIST 0x10
+
+/** Returns event-base type. Could be "mini-event", "winsock-event" for the
+ * daemon compile, and will be "pluggable-event<PACKAGE_VERSION>" for
+ * libunbound.
+ */
+const char* ub_event_get_version(void);
+/** Return the name, system and method for the pluggable event base */
+void ub_get_event_sys(struct ub_event_base*, const char** n, const char** s,
+ const char** m);
+/** Return a default event base. In the deamon thess will be the only event
+ * bases used.
+ */
+struct ub_event_base* ub_default_event_base(int, time_t*, struct timeval*);
+/** Return an ub_event_base constructed for the given libevent event base */
+struct ub_event_base* ub_libevent_event_base(struct event_base*);
+/** Return the libevent base underlying the given ub_event_base. Will return
+ * NULL when the ub_event_base does not have an underlying libevent event base
+ */
+struct event_base* ub_libevent_get_event_base(struct ub_event_base*);
+/** Free event base. Free events yourself */
+void ub_event_base_free(struct ub_event_base*);
+/** Run the event base */
+int ub_event_base_dispatch(struct ub_event_base*);
+/** exit that loop */
+int ub_event_base_loopexit(struct ub_event_base*);
+
+/** Create a new ub_event for the event base */
+struct ub_event* ub_event_new(struct ub_event_base*,
+ int fd, short bits, void (*cb)(int, short, void*), void* arg);
+/** Create a new ub_event signal for the event base */
+struct ub_event* ub_signal_new(struct ub_event_base*, int fd,
+ void (*cb)(int, short, void*), void* arg);
+/** Create a new ub_event associated with the wsaevent for the event base */
+struct ub_event* ub_winsock_register_wsaevent(struct ub_event_base*,
+ void* wsaevent, void (*cb)(int, short, void*), void* arg);
+
+/** Add event bits for this event to fire on */
+void ub_event_add_bits(struct ub_event*, short bits);
+ /** Configure the event so it will not longer fire on given bits */
+void ub_event_del_bits(struct ub_event*, short bits);
+/** Change or set the file descriptor on the event */
+void ub_event_set_fd(struct ub_event*, int fd);
+/** free the event */
+void ub_event_free(struct ub_event*);
+/** Activate the event. The given timeval is an timeout value. */
+int ub_event_add(struct ub_event*, struct timeval*);
+/** Deactivate the event */
+int ub_event_del(struct ub_event*);
+/** Reconfigure and activate a timeout event */
+int ub_timer_add(struct ub_event*, struct ub_event_base*,
+ void (*cb)(int, short, void*), void* arg, struct timeval*);
+/** Deactivate the timeout event */
+int ub_timer_del(struct ub_event*);
+/** Activate a signal event */
+int ub_signal_add(struct ub_event*, struct timeval*);
+/** Deactivate a signal event */
+int ub_signal_del(struct ub_event*);
+/** Free a with a wsaevent associated event */
+void ub_winsock_unregister_wsaevent(struct ub_event* ev);
+/** Signal the eventloop when a TCP windows socket will block on next read
+ * or write (given by the eventbits)
+ */
+void ub_winsock_tcp_wouldblock(struct ub_event*, int bits);
+/** Equip the comm_base with the current time */
+void ub_comm_base_now(struct comm_base* cb);
+
+#endif /* UB_EVENT_H */
diff --git a/contrib/unbound/util/ub_event_pluggable.c b/contrib/unbound/util/ub_event_pluggable.c
new file mode 100644
index 0000000..4a94512
--- /dev/null
+++ b/contrib/unbound/util/ub_event_pluggable.c
@@ -0,0 +1,692 @@
+/*
+ * util/ub_event_pluggable.c - call registered pluggable event functions
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * 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 of the NLNET LABS 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
+ * HOLDER 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.
+ */
+
+/**
+ * \file
+ *
+ * This file contains an implementation for the indirection layer for pluggable
+ * events that calls the registered pluggable event loop. It also defines a
+ * default pluggable event loop based on the default libevent (compatibility)
+ * functions.
+ */
+#include "config.h"
+#include <sys/time.h>
+#include "util/ub_event.h"
+#include "libunbound/unbound-event.h"
+#include "util/netevent.h"
+#include "util/log.h"
+#include "util/fptr_wlist.h"
+
+/* We define libevent structures here to hide the libevent stuff. */
+
+#ifdef USE_MINI_EVENT
+# ifdef USE_WINSOCK
+# include "util/winsock_event.h"
+# else
+# include "util/mini_event.h"
+# endif /* USE_WINSOCK */
+#else /* USE_MINI_EVENT */
+ /* we use libevent */
+# ifdef HAVE_EVENT_H
+# include <event.h>
+# else
+# include "event2/event.h"
+# include "event2/event_struct.h"
+# include "event2/event_compat.h"
+# endif
+#endif /* USE_MINI_EVENT */
+
+#if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \
+ UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \
+ UB_EV_PERSIST != EV_PERSIST
+/* Only necessary for libev */
+# define NATIVE_BITS(b) ( \
+ (((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \
+ | (((b) & UB_EV_READ ) ? EV_READ : 0) \
+ | (((b) & UB_EV_WRITE ) ? EV_WRITE : 0) \
+ | (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL : 0) \
+ | (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0))
+
+# define UB_EV_BITS(b) ( \
+ (((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \
+ | (((b) & EV_READ ) ? UB_EV_READ : 0) \
+ | (((b) & EV_WRITE ) ? UB_EV_WRITE : 0) \
+ | (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL : 0) \
+ | (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0))
+
+# define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \
+ { (C)(fd, UB_EV_BITS(bits), arg); }
+
+UB_EV_BITS_CB(comm_point_udp_callback);
+UB_EV_BITS_CB(comm_point_udp_ancil_callback)
+UB_EV_BITS_CB(comm_point_tcp_accept_callback)
+UB_EV_BITS_CB(comm_point_tcp_handle_callback)
+UB_EV_BITS_CB(comm_timer_callback)
+UB_EV_BITS_CB(comm_signal_callback)
+UB_EV_BITS_CB(comm_point_local_handle_callback)
+UB_EV_BITS_CB(comm_point_raw_handle_callback)
+UB_EV_BITS_CB(tube_handle_signal)
+UB_EV_BITS_CB(comm_base_handle_slow_accept)
+
+static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
+{
+ if(cb == comm_point_udp_callback)
+ return my_comm_point_udp_callback;
+ else if(cb == comm_point_udp_ancil_callback)
+ return my_comm_point_udp_ancil_callback;
+ else if(cb == comm_point_tcp_accept_callback)
+ return my_comm_point_tcp_accept_callback;
+ else if(cb == comm_point_tcp_handle_callback)
+ return my_comm_point_tcp_handle_callback;
+ else if(cb == comm_timer_callback)
+ return my_comm_timer_callback;
+ else if(cb == comm_signal_callback)
+ return my_comm_signal_callback;
+ else if(cb == comm_point_local_handle_callback)
+ return my_comm_point_local_handle_callback;
+ else if(cb == comm_point_raw_handle_callback)
+ return my_comm_point_raw_handle_callback;
+ else if(cb == tube_handle_signal)
+ return my_tube_handle_signal;
+ else if(cb == comm_base_handle_slow_accept)
+ return my_comm_base_handle_slow_accept;
+ else
+ return NULL;
+}
+#else
+# define NATIVE_BITS(b) (b)
+# define NATIVE_BITS_CB(c) (c)
+#endif
+
+#ifndef EVFLAG_AUTO
+#define EVFLAG_AUTO 0
+#endif
+
+struct my_event_base {
+ struct ub_event_base super;
+ struct event_base* base;
+};
+
+struct my_event {
+ struct ub_event super;
+ struct event ev;
+};
+
+#define AS_MY_EVENT_BASE(x) ((struct my_event_base*)x)
+#define AS_MY_EVENT(x) ((struct my_event*)x)
+
+const char* ub_event_get_version(void)
+{
+ return "pluggable-event"PACKAGE_VERSION;
+}
+
+static void
+my_event_add_bits(struct ub_event* ev, short bits)
+{
+ AS_MY_EVENT(ev)->ev.ev_events |= NATIVE_BITS(bits);
+}
+
+static void
+my_event_del_bits(struct ub_event* ev, short bits)
+{
+ AS_MY_EVENT(ev)->ev.ev_events &= ~NATIVE_BITS(bits);
+}
+
+static void
+my_event_set_fd(struct ub_event* ev, int fd)
+{
+ AS_MY_EVENT(ev)->ev.ev_fd = fd;
+}
+
+static void
+my_event_free(struct ub_event* ev)
+{
+ free(AS_MY_EVENT(ev));
+}
+
+static int
+my_event_add(struct ub_event* ev, struct timeval* tv)
+{
+ return event_add(&AS_MY_EVENT(ev)->ev, tv);
+}
+
+static int
+my_event_del(struct ub_event* ev)
+{
+ return event_del(&AS_MY_EVENT(ev)->ev);
+}
+
+static int
+my_timer_add(struct ub_event* ev, struct ub_event_base* base,
+ void (*cb)(int, short, void*), void* arg, struct timeval* tv)
+{
+ event_set(&AS_MY_EVENT(ev)->ev, -1, EV_TIMEOUT,NATIVE_BITS_CB(cb),arg);
+ if (event_base_set(AS_MY_EVENT_BASE(base)->base, &AS_MY_EVENT(ev)->ev)
+ != 0)
+ return -1;
+ return evtimer_add(&AS_MY_EVENT(ev)->ev, tv);
+}
+
+static int
+my_timer_del(struct ub_event* ev)
+{
+ return evtimer_del(&AS_MY_EVENT(ev)->ev);
+}
+
+static int
+my_signal_add(struct ub_event* ev, struct timeval* tv)
+{
+ return signal_add(&AS_MY_EVENT(ev)->ev, tv);
+}
+
+static int
+my_signal_del(struct ub_event* ev)
+{
+ return signal_del(&AS_MY_EVENT(ev)->ev);
+}
+
+static void
+my_winsock_unregister_wsaevent(struct ub_event* ev)
+{
+#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
+ winsock_unregister_wsaevent(&AS_MY_EVENT(ev)->ev);
+ free(AS_MY_EVENT(ev));
+#else
+ (void)ev;
+#endif
+}
+
+static void
+my_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
+{
+#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
+ winsock_tcp_wouldblock(&AS_MY_EVENT(ev)->ev, NATIVE_BITS(eventbits));
+#else
+ (void)ev;
+ (void)eventbits;
+#endif
+}
+
+static struct ub_event_vmt default_event_vmt = {
+ my_event_add_bits, my_event_del_bits, my_event_set_fd,
+ my_event_free, my_event_add, my_event_del,
+ my_timer_add, my_timer_del, my_signal_add, my_signal_del,
+ my_winsock_unregister_wsaevent, my_winsock_tcp_wouldblock
+};
+
+static void
+my_event_base_free(struct ub_event_base* base)
+{
+#ifdef USE_MINI_EVENT
+ event_base_free(AS_MY_EVENT_BASE(base)->base);
+#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
+ /* only libevent 1.2+ has it, but in 1.2 it is broken -
+ assertion fails on signal handling ev that is not deleted
+ in libevent 1.3c (event_base_once appears) this is fixed. */
+ event_base_free(AS_MY_EVENT_BASE(base)->base);
+#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
+ free(AS_MY_EVENT_BASE(base));
+}
+
+static int
+my_event_base_dispatch(struct ub_event_base* base)
+{
+ return event_base_dispatch(AS_MY_EVENT_BASE(base)->base);
+}
+
+static int
+my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv)
+{
+ return event_base_loopexit(AS_MY_EVENT_BASE(base)->base, tv);
+}
+
+static struct ub_event*
+my_event_new(struct ub_event_base* base, int fd, short bits,
+ void (*cb)(int, short, void*), void* arg)
+{
+ struct my_event *my_ev = (struct my_event*)calloc(1,
+ sizeof(struct my_event));
+
+ if (!my_ev)
+ return NULL;
+
+ event_set(&my_ev->ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
+ if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
+ free(my_ev);
+ return NULL;
+ }
+ my_ev->super.magic = UB_EVENT_MAGIC;
+ my_ev->super.vmt = &default_event_vmt;
+ return &my_ev->super;
+}
+
+static struct ub_event*
+my_signal_new(struct ub_event_base* base, int fd,
+ void (*cb)(int, short, void*), void* arg)
+{
+ struct my_event *my_ev = (struct my_event*)calloc(1,
+ sizeof(struct my_event));
+
+ if (!my_ev)
+ return NULL;
+
+ signal_set(&my_ev->ev, fd, NATIVE_BITS_CB(cb), arg);
+ if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
+ free(my_ev);
+ return NULL;
+ }
+ my_ev->super.magic = UB_EVENT_MAGIC;
+ my_ev->super.vmt = &default_event_vmt;
+ return &my_ev->super;
+}
+
+static struct ub_event*
+my_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
+ void (*cb)(int, short, void*), void* arg)
+{
+#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
+ struct my_event *my_ev = (struct my_event*)calloc(1,
+ sizeof(struct my_event));
+
+ if (!my_ev)
+ return NULL;
+
+ if (!winsock_register_wsaevent(AS_MY_EVENT_BASE(base)->base,
+ &my_ev->ev, wsaevent, cb, arg)) {
+ free(my_ev);
+ return NULL;
+
+ }
+ my_ev->super.magic = UB_EVENT_MAGIC;
+ my_ev->super.vmt = &default_event_vmt;
+ return &my_ev->super;
+#else
+ (void)base;
+ (void)wsaevent;
+ (void)cb;
+ (void)arg;
+ return NULL;
+#endif
+}
+
+static struct ub_event_base_vmt default_event_base_vmt = {
+ my_event_base_free, my_event_base_dispatch,
+ my_event_base_loopexit, my_event_new, my_signal_new,
+ my_winsock_register_wsaevent
+};
+
+struct ub_event_base*
+ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv)
+{
+ struct my_event_base* my_base = (struct my_event_base*)calloc(1,
+ sizeof(struct my_event_base));
+
+ if (!my_base)
+ return NULL;
+
+#ifdef USE_MINI_EVENT
+ (void)sigs;
+ /* use mini event time-sharing feature */
+ my_base->base = event_init(time_secs, time_tv);
+#else
+ (void)time_secs;
+ (void)time_tv;
+# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
+ /* libev */
+ if(sigs)
+ my_base->base = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
+ else
+ my_base->base = (struct event_base*)ev_loop_new(EVFLAG_AUTO);
+# else
+ (void)sigs;
+# ifdef HAVE_EVENT_BASE_NEW
+ my_base->base = event_base_new();
+# else
+ my_base->base = event_init();
+# endif
+# endif
+#endif
+ if (!my_base->base) {
+ free(my_base);
+ return NULL;
+ }
+ my_base->super.magic = UB_EVENT_MAGIC;
+ my_base->super.vmt = &default_event_base_vmt;
+ return &my_base->super;
+}
+
+struct ub_event_base*
+ub_libevent_event_base(struct event_base* base)
+{
+#ifdef USE_MINI_EVENT
+ (void)base;
+ return NULL;
+#else
+ struct my_event_base* my_base = (struct my_event_base*)calloc(1,
+ sizeof(struct my_event_base));
+
+ if (!my_base)
+ return NULL;
+ my_base->super.magic = UB_EVENT_MAGIC;
+ my_base->super.vmt = &default_event_base_vmt;
+ my_base->base = base;
+ return &my_base->super;
+#endif
+}
+
+struct event_base*
+ub_libevent_get_event_base(struct ub_event_base* base)
+{
+#ifndef USE_MINI_EVENT
+ if (base->vmt == &default_event_base_vmt)
+ return AS_MY_EVENT_BASE(base)->base;
+#else
+ (void)base;
+#endif
+ return NULL;
+}
+
+#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
+static const char* ub_ev_backend2str_pluggable(int b)
+{
+ switch(b) {
+ case EVBACKEND_SELECT: return "select";
+ case EVBACKEND_POLL: return "poll";
+ case EVBACKEND_EPOLL: return "epoll";
+ case EVBACKEND_KQUEUE: return "kqueue";
+ case EVBACKEND_DEVPOLL: return "devpoll";
+ case EVBACKEND_PORT: return "evport";
+ }
+ return "unknown";
+}
+#endif
+
+void
+ub_get_event_sys(struct ub_event_base* ub_base, const char** n, const char** s,
+ const char** m)
+{
+#ifdef USE_WINSOCK
+ (void)ub_base;
+ *n = "pluggable-event";
+ *s = "winsock";
+ *m = "WSAWaitForMultipleEvents";
+#elif defined(USE_MINI_EVENT)
+ (void)ub_base;
+ *n = "pluggable-event";
+ *s = "internal";
+ *m = "select";
+#else
+ struct event_base* b = ub_libevent_get_event_base(ub_base);
+ /* This function is only called from comm_base_create, so
+ * ub_base is guaranteed to exist and to be the default
+ * event base.
+ */
+ assert(b);
+ *n = "pluggable-event";
+ *s = event_get_version();
+# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
+ *n = "pluggable-libev";
+# ifdef EVBACKEND_SELECT
+ *m = ub_ev_backend2str_pluggable(ev_backend((struct ev_loop*)b));
+# else
+ *m = "not obtainable";
+# endif
+# elif defined(HAVE_EVENT_BASE_GET_METHOD)
+ *n = "pluggable-libevent";
+ *m = event_base_get_method(b);
+# else
+ *m = "not obtainable";
+# endif
+#endif
+}
+
+void
+ub_event_base_free(struct ub_event_base* base)
+{
+ if (base && base->magic == UB_EVENT_MAGIC) {
+ fptr_ok(base->vmt != &default_event_base_vmt ||
+ base->vmt->free == my_event_base_free);
+ (*base->vmt->free)(base);
+ }
+}
+
+int
+ub_event_base_dispatch(struct ub_event_base* base)
+{
+ if (base->magic == UB_EVENT_MAGIC) {
+ fptr_ok(base->vmt != &default_event_base_vmt ||
+ base->vmt->dispatch == my_event_base_dispatch);
+ return (*base->vmt->dispatch)(base);
+ }
+ return -1;
+}
+
+int
+ub_event_base_loopexit(struct ub_event_base* base)
+{
+ if (base->magic == UB_EVENT_MAGIC) {
+ fptr_ok(base->vmt != &default_event_base_vmt ||
+ base->vmt->loopexit == my_event_base_loopexit);
+ return (*base->vmt->loopexit)(base, NULL);
+ }
+ return -1;
+}
+
+struct ub_event*
+ub_event_new(struct ub_event_base* base, int fd, short bits,
+ void (*cb)(int, short, void*), void* arg)
+{
+ if (base->magic == UB_EVENT_MAGIC) {
+ fptr_ok(base->vmt != &default_event_base_vmt ||
+ base->vmt->new_event == my_event_new);
+ return (*base->vmt->new_event)(base, fd, bits, cb, arg);
+ }
+ return NULL;
+}
+
+struct ub_event*
+ub_signal_new(struct ub_event_base* base, int fd,
+ void (*cb)(int, short, void*), void* arg)
+{
+ if (base->magic == UB_EVENT_MAGIC) {
+ fptr_ok(base->vmt != &default_event_base_vmt ||
+ base->vmt->new_signal == my_signal_new);
+ return (*base->vmt->new_signal)(base, fd, cb, arg);
+ }
+ return NULL;
+}
+
+struct ub_event*
+ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
+ void (*cb)(int, short, void*), void* arg)
+{
+ if (base->magic == UB_EVENT_MAGIC) {
+ fptr_ok(base->vmt != &default_event_base_vmt ||
+ base->vmt->winsock_register_wsaevent ==
+ my_winsock_register_wsaevent);
+ return (*base->vmt->winsock_register_wsaevent)(base, wsaevent, cb, arg);
+ }
+ return NULL;
+}
+
+void
+ub_event_add_bits(struct ub_event* ev, short bits)
+{
+ if (ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->add_bits == my_event_add_bits);
+ (*ev->vmt->add_bits)(ev, bits);
+ }
+}
+
+void
+ub_event_del_bits(struct ub_event* ev, short bits)
+{
+ if (ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->del_bits == my_event_del_bits);
+ (*ev->vmt->del_bits)(ev, bits);
+ }
+}
+
+void
+ub_event_set_fd(struct ub_event* ev, int fd)
+{
+ if (ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->set_fd == my_event_set_fd);
+ (*ev->vmt->set_fd)(ev, fd);
+ }
+}
+
+void
+ub_event_free(struct ub_event* ev)
+{
+ if (ev && ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->free == my_event_free);
+ (*ev->vmt->free)(ev);
+ }
+}
+
+int
+ub_event_add(struct ub_event* ev, struct timeval* tv)
+{
+ if (ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->add == my_event_add);
+ return (*ev->vmt->add)(ev, tv);
+ }
+ return -1;
+}
+
+int
+ub_event_del(struct ub_event* ev)
+{
+ if (ev && ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->del == my_event_del);
+ return (*ev->vmt->del)(ev);
+ }
+ return -1;
+}
+
+int
+ub_timer_add(struct ub_event* ev, struct ub_event_base* base,
+ void (*cb)(int, short, void*), void* arg, struct timeval* tv)
+{
+ if (ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->add_timer == my_timer_add);
+ return (*ev->vmt->add_timer)(ev, base, cb, arg, tv);
+ }
+ return -1;
+}
+
+int
+ub_timer_del(struct ub_event* ev)
+{
+ if (ev && ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->del_timer == my_timer_del);
+ return (*ev->vmt->del_timer)(ev);
+ }
+ return -1;
+}
+
+int
+ub_signal_add(struct ub_event* ev, struct timeval* tv)
+{
+ if (ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->add_signal == my_signal_add);
+ return (*ev->vmt->add_signal)(ev, tv);
+ }
+ return -1;
+}
+
+int
+ub_signal_del(struct ub_event* ev)
+{
+ if (ev && ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->del_signal == my_signal_del);
+ return (*ev->vmt->del_signal)(ev);
+ }
+ return -1;
+}
+
+void
+ub_winsock_unregister_wsaevent(struct ub_event* ev)
+{
+ if (ev && ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->winsock_unregister_wsaevent ==
+ my_winsock_unregister_wsaevent);
+ (*ev->vmt->winsock_unregister_wsaevent)(ev);
+ }
+}
+
+void
+ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
+{
+ if (ev->magic == UB_EVENT_MAGIC) {
+ fptr_ok(ev->vmt != &default_event_vmt ||
+ ev->vmt->winsock_tcp_wouldblock ==
+ my_winsock_tcp_wouldblock);
+ (*ev->vmt->winsock_tcp_wouldblock)(ev, eventbits);
+ }
+}
+
+void ub_comm_base_now(struct comm_base* cb)
+{
+ time_t *tt;
+ struct timeval *tv;
+
+#ifdef USE_MINI_EVENT
+/** minievent updates the time when it blocks. */
+ if (comm_base_internal(cb)->magic == UB_EVENT_MAGIC &&
+ comm_base_internal(cb)->vmt == &default_event_base_vmt)
+ return; /* Actually using mini event, so do not set time */
+#endif /* USE_MINI_EVENT */
+
+/** fillup the time values in the event base */
+ comm_base_timept(cb, &tt, &tv);
+ if(gettimeofday(tv, NULL) < 0) {
+ log_err("gettimeofday: %s", strerror(errno));
+ }
+ *tt = tv->tv_sec;
+}
+
diff --git a/contrib/unbound/util/winsock_event.c b/contrib/unbound/util/winsock_event.c
index 40b7982..9aad27e 100644
--- a/contrib/unbound/util/winsock_event.c
+++ b/contrib/unbound/util/winsock_event.c
@@ -262,8 +262,9 @@ static int handle_select(struct event_base* base, struct timeval* wait)
break; /* sanity check */
}
log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);
- verbose(VERB_CLIENT, "winsock_event bmax=%d numwait=%d wait=%x "
- "timeout=%d", base->max, numwait, (int)wait, (int)timeout);
+ verbose(VERB_CLIENT, "winsock_event bmax=%d numwait=%d wait=%s "
+ "timeout=%d", base->max, numwait, (wait?"<wait>":"<null>"),
+ (int)timeout);
/* do the wait */
if(numwait == 0) {
diff --git a/contrib/unbound/validator/autotrust.c b/contrib/unbound/validator/autotrust.c
index f8c9c8c..da8829c 100644
--- a/contrib/unbound/validator/autotrust.c
+++ b/contrib/unbound/validator/autotrust.c
@@ -430,6 +430,8 @@ find_add_tp(struct val_anchors* anchors, uint8_t* rr, size_t rr_len,
}
tp = autr_tp_create(anchors, rr, dname_len, sldns_wirerr_get_class(rr,
rr_len, dname_len));
+ if(!tp)
+ return NULL;
lock_basic_lock(&tp->lock);
return tp;
}
@@ -1201,7 +1203,7 @@ void autr_write_file(struct module_env* env, struct trust_anchor* tp)
if(fsync(fileno(out)) != 0)
log_err("could not fsync(%s): %s", fname, strerror(errno));
#else
- FlushFileBuffers((HANDLE)_fileno(out));
+ FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
#endif
if(fclose(out) != 0) {
fatal_exit("could not complete write: %s: %s",
@@ -2333,6 +2335,7 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
edns.ext_rcode = 0;
edns.edns_version = 0;
edns.bits = EDNS_DO;
+ edns.opt_list = NULL;
if(sldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
else edns.udp_size = 65535;
diff --git a/contrib/unbound/validator/val_anchor.c b/contrib/unbound/validator/val_anchor.c
index bc9f8b8..4d470b6 100644
--- a/contrib/unbound/validator/val_anchor.c
+++ b/contrib/unbound/validator/val_anchor.c
@@ -1030,6 +1030,8 @@ anchors_assemble_rrsets(struct val_anchors* anchors)
")", b);
(void)rbtree_delete(anchors->tree, &ta->node);
lock_basic_unlock(&ta->lock);
+ if(anchors->dlv_anchor == ta)
+ anchors->dlv_anchor = NULL;
anchors_delfunc(&ta->node, NULL);
ta = next;
continue;
diff --git a/contrib/unbound/validator/val_secalgo.c b/contrib/unbound/validator/val_secalgo.c
index baa4dae..e3a1555 100644
--- a/contrib/unbound/validator/val_secalgo.c
+++ b/contrib/unbound/validator/val_secalgo.c
@@ -98,6 +98,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
}
}
+void
+secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
+{
+ (void)SHA256(buf, len, res);
+}
+
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
@@ -186,8 +192,10 @@ dnskey_algo_id_is_supported(int id)
case LDNS_RSAMD5:
/* RFC 6725 deprecates RSAMD5 */
return 0;
+#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
+#endif
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
@@ -227,6 +235,7 @@ log_crypto_error(const char* str, unsigned long e)
log_err("%s crypto %s", str, buf);
}
+#ifdef USE_DSA
/**
* Setup DSA key digest in DER encoding ...
* @param sig: input is signature output alloced ptr (unless failure).
@@ -268,6 +277,7 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
DSA_SIG_free(dsasig);
return 1;
}
+#endif /* USE_DSA */
#ifdef USE_ECDSA
/**
@@ -281,36 +291,82 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
static int
setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
{
- ECDSA_SIG* ecdsa_sig;
- int newlen;
+ /* convert from two BIGNUMs in the rdata buffer, to ASN notation.
+ * ASN preable: 30440220 <R 32bytefor256> 0220 <S 32bytefor256>
+ * the '20' is the length of that field (=bnsize).
+i * the '44' is the total remaining length.
+ * if negative, start with leading zero.
+ * if starts with 00s, remove them from the number.
+ */
+ uint8_t pre[] = {0x30, 0x44, 0x02, 0x20};
+ int pre_len = 4;
+ uint8_t mid[] = {0x02, 0x20};
+ int mid_len = 2;
+ int raw_sig_len, r_high, s_high, r_rem=0, s_rem=0;
int bnsize = (int)((*len)/2);
+ unsigned char* d = *sig;
+ uint8_t* p;
/* if too short or not even length, fails */
if(*len < 16 || bnsize*2 != (int)*len)
return 0;
- /* use the raw data to parse two evenly long BIGNUMs, "r | s". */
- ecdsa_sig = ECDSA_SIG_new();
- if(!ecdsa_sig) return 0;
- ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r);
- ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s);
- if(!ecdsa_sig->r || !ecdsa_sig->s) {
- ECDSA_SIG_free(ecdsa_sig);
- return 0;
- }
- /* spool it into ASN format */
- *sig = NULL;
- newlen = i2d_ECDSA_SIG(ecdsa_sig, sig);
- if(newlen <= 0) {
- ECDSA_SIG_free(ecdsa_sig);
- free(*sig);
+ /* strip leading zeroes from r (but not last one) */
+ while(r_rem < bnsize-1 && d[r_rem] == 0)
+ r_rem++;
+ /* strip leading zeroes from s (but not last one) */
+ while(s_rem < bnsize-1 && d[bnsize+s_rem] == 0)
+ s_rem++;
+
+ r_high = ((d[0+r_rem]&0x80)?1:0);
+ s_high = ((d[bnsize+s_rem]&0x80)?1:0);
+ raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len +
+ s_high + bnsize - s_rem;
+ *sig = (unsigned char*)malloc((size_t)raw_sig_len);
+ if(!*sig)
return 0;
+ p = (uint8_t*)*sig;
+ p[0] = pre[0];
+ p[1] = (uint8_t)(raw_sig_len-2);
+ p[2] = pre[2];
+ p[3] = (uint8_t)(bnsize + r_high - r_rem);
+ p += 4;
+ if(r_high) {
+ *p = 0;
+ p += 1;
}
- *len = (unsigned int)newlen;
- ECDSA_SIG_free(ecdsa_sig);
+ memmove(p, d+r_rem, (size_t)bnsize-r_rem);
+ p += bnsize-r_rem;
+ memmove(p, mid, (size_t)mid_len-1);
+ p += mid_len-1;
+ *p = (uint8_t)(bnsize + s_high - s_rem);
+ p += 1;
+ if(s_high) {
+ *p = 0;
+ p += 1;
+ }
+ memmove(p, d+bnsize+s_rem, (size_t)bnsize-s_rem);
+ *len = (unsigned int)raw_sig_len;
return 1;
}
#endif /* USE_ECDSA */
+#ifdef USE_ECDSA_EVP_WORKAROUND
+static EVP_MD ecdsa_evp_256_md;
+static EVP_MD ecdsa_evp_384_md;
+void ecdsa_evp_workaround_init(void)
+{
+ /* openssl before 1.0.0 fixes RSA with the SHA256
+ * hash in EVP. We create one for ecdsa_sha256 */
+ ecdsa_evp_256_md = *EVP_sha256();
+ ecdsa_evp_256_md.required_pkey_type[0] = EVP_PKEY_EC;
+ ecdsa_evp_256_md.verify = (void*)ECDSA_verify;
+
+ ecdsa_evp_384_md = *EVP_sha384();
+ ecdsa_evp_384_md.required_pkey_type[0] = EVP_PKEY_EC;
+ ecdsa_evp_384_md.verify = (void*)ECDSA_verify;
+}
+#endif /* USE_ECDSA_EVP_WORKAROUND */
+
/**
* Setup key and digest for verification. Adjust sig if necessary.
*
@@ -325,10 +381,13 @@ static int
setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
unsigned char* key, size_t keylen)
{
+#ifdef USE_DSA
DSA* dsa;
+#endif
RSA* rsa;
switch(algo) {
+#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*evp_key = EVP_PKEY_new();
@@ -350,6 +409,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
*digest_type = EVP_dss1();
break;
+#endif /* USE_DSA */
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
@@ -435,20 +495,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
return 0;
}
#ifdef USE_ECDSA_EVP_WORKAROUND
- /* openssl before 1.0.0 fixes RSA with the SHA256
- * hash in EVP. We create one for ecdsa_sha256 */
- {
- static int md_ecdsa_256_done = 0;
- static EVP_MD md;
- if(!md_ecdsa_256_done) {
- EVP_MD m = *EVP_sha256();
- md_ecdsa_256_done = 1;
- m.required_pkey_type[0] = (*evp_key)->type;
- m.verify = (void*)ECDSA_verify;
- md = m;
- }
- *digest_type = &md;
- }
+ *digest_type = &ecdsa_evp_256_md;
#else
*digest_type = EVP_sha256();
#endif
@@ -462,20 +509,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
return 0;
}
#ifdef USE_ECDSA_EVP_WORKAROUND
- /* openssl before 1.0.0 fixes RSA with the SHA384
- * hash in EVP. We create one for ecdsa_sha384 */
- {
- static int md_ecdsa_384_done = 0;
- static EVP_MD md;
- if(!md_ecdsa_384_done) {
- EVP_MD m = *EVP_sha384();
- md_ecdsa_384_done = 1;
- m.required_pkey_type[0] = (*evp_key)->type;
- m.verify = (void*)ECDSA_verify;
- md = m;
- }
- *digest_type = &md;
- }
+ *digest_type = &ecdsa_evp_384_md;
#else
*digest_type = EVP_sha384();
#endif
@@ -508,8 +542,8 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
char** reason)
{
const EVP_MD *digest_type;
- EVP_MD_CTX ctx;
- int res, dofree = 0;
+ EVP_MD_CTX* ctx;
+ int res, dofree = 0, docrypto_free = 0;
EVP_PKEY *evp_key = NULL;
if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
@@ -518,6 +552,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
EVP_PKEY_free(evp_key);
return sec_status_bogus;
}
+#ifdef USE_DSA
/* if it is a DSA signature in bind format, convert to DER format */
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&
sigblock_len == 1+2*SHA_DIGEST_LENGTH) {
@@ -527,10 +562,14 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
EVP_PKEY_free(evp_key);
return sec_status_bogus;
}
- dofree = 1;
+ docrypto_free = 1;
}
+#endif
+#if defined(USE_ECDSA) && defined(USE_DSA)
+ else
+#endif
#ifdef USE_ECDSA
- else if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
+ if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
/* EVP uses ASN prefix on sig, which is not in the wire data */
if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
@@ -543,32 +582,48 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
#endif /* USE_ECDSA */
/* do the signature cryptography work */
- EVP_MD_CTX_init(&ctx);
- if(EVP_VerifyInit(&ctx, digest_type) == 0) {
- verbose(VERB_QUERY, "verify: EVP_VerifyInit failed");
+#ifdef HAVE_EVP_MD_CTX_NEW
+ ctx = EVP_MD_CTX_new();
+#else
+ ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx));
+ if(ctx) EVP_MD_CTX_init(ctx);
+#endif
+ if(!ctx) {
+ log_err("EVP_MD_CTX_new: malloc failure");
EVP_PKEY_free(evp_key);
if(dofree) free(sigblock);
+ else if(docrypto_free) OPENSSL_free(sigblock);
return sec_status_unchecked;
}
- if(EVP_VerifyUpdate(&ctx, (unsigned char*)sldns_buffer_begin(buf),
- (unsigned int)sldns_buffer_limit(buf)) == 0) {
- verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed");
+ if(EVP_VerifyInit(ctx, digest_type) == 0) {
+ verbose(VERB_QUERY, "verify: EVP_VerifyInit failed");
+ EVP_MD_CTX_destroy(ctx);
EVP_PKEY_free(evp_key);
if(dofree) free(sigblock);
+ else if(docrypto_free) OPENSSL_free(sigblock);
return sec_status_unchecked;
}
-
- res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key);
- if(EVP_MD_CTX_cleanup(&ctx) == 0) {
- verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed");
+ if(EVP_VerifyUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf),
+ (unsigned int)sldns_buffer_limit(buf)) == 0) {
+ verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed");
+ EVP_MD_CTX_destroy(ctx);
EVP_PKEY_free(evp_key);
if(dofree) free(sigblock);
+ else if(docrypto_free) OPENSSL_free(sigblock);
return sec_status_unchecked;
}
+
+ res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key);
+#ifdef HAVE_EVP_MD_CTX_NEW
+ EVP_MD_CTX_destroy(ctx);
+#else
+ EVP_MD_CTX_cleanup(ctx);
+ free(ctx);
+#endif
EVP_PKEY_free(evp_key);
- if(dofree)
- free(sigblock);
+ if(dofree) free(sigblock);
+ else if(docrypto_free) OPENSSL_free(sigblock);
if(res == 1) {
return sec_status_secure;
@@ -620,6 +675,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
}
}
+void
+secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
+{
+ (void)HASH_HashBuf(HASH_AlgSHA256, res, buf, (unsigned long)len);
+}
+
size_t
ds_digest_size_supported(int algo)
{
@@ -678,8 +739,10 @@ dnskey_algo_id_is_supported(int id)
case LDNS_RSAMD5:
/* RFC 6725 deprecates RSAMD5 */
return 0;
+#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
+#endif
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#ifdef USE_SHA2
@@ -920,6 +983,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*/
switch(algo) {
+#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*pubkey = nss_buf2dsa(key, keylen);
@@ -930,6 +994,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*htype = HASH_AlgSHA1;
/* no prefix for DSA verification */
break;
+#endif
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#ifdef USE_SHA2
@@ -1046,6 +1111,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_bogus;
}
+#ifdef USE_DSA
/* need to convert DSA, ECDSA signatures? */
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) {
if(sigblock_len == 1+2*SHA1_LENGTH) {
@@ -1068,6 +1134,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
SECITEM_FreeItem(p, PR_TRUE);
}
}
+#endif /* USE_DSA */
/* do the signature cryptography work */
/* hash the data */
@@ -1131,6 +1198,9 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
#include "macros.h"
#include "rsa.h"
#include "dsa.h"
+#ifdef HAVE_NETTLE_DSA_COMPAT_H
+#include "dsa-compat.h"
+#endif
#include "asn1.h"
#ifdef USE_ECDSA
#include "ecdsa.h"
@@ -1206,6 +1276,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
}
}
+void
+secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
+{
+ _digest_nettle(SHA256_DIGEST_SIZE, (uint8_t*)buf, len, res);
+}
+
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
@@ -1263,8 +1339,10 @@ dnskey_algo_id_is_supported(int id)
{
/* uses libnettle */
switch(id) {
+#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
+#endif
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#ifdef USE_SHA2
@@ -1283,6 +1361,7 @@ dnskey_algo_id_is_supported(int id)
}
}
+#ifdef USE_DSA
static char *
_verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
@@ -1370,6 +1449,7 @@ _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
else
return NULL;
}
+#endif /* USE_DSA */
static char *
_verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock,
@@ -1541,6 +1621,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
}
switch(algo) {
+#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
@@ -1548,6 +1629,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_bogus;
else
return sec_status_secure;
+#endif /* USE_DSA */
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
diff --git a/contrib/unbound/validator/val_secalgo.h b/contrib/unbound/validator/val_secalgo.h
index 589f1f1..52aaeb9 100644
--- a/contrib/unbound/validator/val_secalgo.h
+++ b/contrib/unbound/validator/val_secalgo.h
@@ -60,6 +60,14 @@ int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
unsigned char* res);
/**
+ * Calculate the sha256 hash for the data buffer into the result.
+ * @param buf: buffer to digest.
+ * @param len: length of the buffer to digest.
+ * @param res: result is stored here (space 256/8 bytes).
+ */
+void secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res);
+
+/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
* @return size in bytes of digest, or 0 if not supported.
diff --git a/contrib/unbound/validator/val_sigcrypt.c b/contrib/unbound/validator/val_sigcrypt.c
index 1dd07b4..e60f3f9 100644
--- a/contrib/unbound/validator/val_sigcrypt.c
+++ b/contrib/unbound/validator/val_sigcrypt.c
@@ -1283,15 +1283,23 @@ adjust_ttl(struct val_env* ve, uint32_t unow,
/* so now:
* d->ttl: rrset ttl read from message or cache. May be reduced
* origttl: original TTL from signature, authoritative TTL max.
+ * MIN_TTL: minimum TTL from config.
* expittl: TTL until the signature expires.
*
- * Use the smallest of these.
+ * Use the smallest of these, but don't let origttl set the TTL
+ * below the minimum.
*/
- if(d->ttl > (time_t)origttl) {
- verbose(VERB_QUERY, "rrset TTL larger than original TTL,"
- " adjusting TTL downwards");
+ if(MIN_TTL > (time_t)origttl && d->ttl > MIN_TTL) {
+ verbose(VERB_QUERY, "rrset TTL larger than original and minimum"
+ " TTL, adjusting TTL downwards to mimimum ttl");
+ d->ttl = MIN_TTL;
+ }
+ else if(MIN_TTL <= origttl && d->ttl > (time_t)origttl) {
+ verbose(VERB_QUERY, "rrset TTL larger than original TTL, "
+ "adjusting TTL downwards to original ttl");
d->ttl = origttl;
}
+
if(expittl > 0 && d->ttl > (time_t)expittl) {
verbose(VERB_ALGO, "rrset TTL larger than sig expiration ttl,"
" adjusting TTL downwards");
diff --git a/contrib/unbound/validator/validator.c b/contrib/unbound/validator/validator.c
index db4383b..f9b6a98 100644
--- a/contrib/unbound/validator/validator.c
+++ b/contrib/unbound/validator/validator.c
@@ -156,6 +156,9 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env,
return 1;
}
+#ifdef USE_ECDSA_EVP_WORKAROUND
+void ecdsa_evp_workaround_init(void);
+#endif
int
val_init(struct module_env* env, int id)
{
@@ -171,6 +174,9 @@ val_init(struct module_env* env, int id)
lock_basic_init(&val_env->bogus_lock);
lock_protect(&val_env->bogus_lock, &val_env->num_rrset_bogus,
sizeof(val_env->num_rrset_bogus));
+#ifdef USE_ECDSA_EVP_WORKAROUND
+ ecdsa_evp_workaround_init();
+#endif
if(!val_apply_cfg(env, val_env, env->cfg)) {
log_err("validator: could not apply configuration settings.");
return 0;
diff --git a/crypto/openssh/kex.c b/crypto/openssh/kex.c
index d371f47..9c9f562 100644
--- a/crypto/openssh/kex.c
+++ b/crypto/openssh/kex.c
@@ -468,6 +468,7 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
if (kex == NULL)
return SSH_ERR_INVALID_ARGUMENT;
+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
ptr = sshpkt_ptr(ssh, &dlen);
if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
return r;
diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist
index f08c13a..1928984 100644
--- a/etc/mtree/BSD.include.dist
+++ b/etc/mtree/BSD.include.dist
@@ -110,6 +110,8 @@
..
ciss
..
+ evdev
+ ..
filemon
..
firewire
diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile
index 9ad9f91..eb66c7b 100644
--- a/etc/rc.d/Makefile
+++ b/etc/rc.d/Makefile
@@ -118,14 +118,17 @@ FILES= DAEMON \
ugidfw \
${_utx} \
var \
- watchdogd \
- ypbind \
+ watchdogd
+
+.if ${MK_NIS} != "no"
+FILES+= ypbind \
ypldap \
yppasswdd \
ypserv \
ypset \
ypupdated \
ypxfrd
+.endif
.if ${MK_ACCT} != "no"
FILESGROUPS+= ACCT
diff --git a/include/Makefile b/include/Makefile
index e4cdf72..0675bf2 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -154,7 +154,7 @@ copies: .PHONY .META
done; \
fi
.endfor
-.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/nand:Ndev/pci} ${LSUBSUBDIRS}
+.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/nand:Ndev/pci} ${LSUBSUBDIRS}
cd ${.CURDIR}/../sys; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \
${DESTDIR}${INCLUDEDIR}/$i
@@ -177,6 +177,13 @@ copies: .PHONY .META
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 nand_dev.h \
${DESTDIR}${INCLUDEDIR}/dev/nand
.endif
+ cd ${.CURDIR}/../sys/dev/evdev; \
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 input.h \
+ ${DESTDIR}${INCLUDEDIR}/dev/evdev; \
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 input-event-codes.h \
+ ${DESTDIR}${INCLUDEDIR}/dev/evdev; \
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 uinput.h \
+ ${DESTDIR}${INCLUDEDIR}/dev/evdev
cd ${.CURDIR}/../sys/dev/pci; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 pcireg.h \
${DESTDIR}${INCLUDEDIR}/dev/pci
@@ -229,6 +236,17 @@ copies: .PHONY .META
cd ${.CURDIR}/../sys/teken; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 teken.h \
${DESTDIR}${INCLUDEDIR}/teken
+.if ${MK_CDDL} != "no"
+ cd ${.CURDIR}/../cddl/contrib/opensolaris/lib/libzfs_core/common; \
+ ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 libzfs_core.h \
+ ${DESTDIR}${INCLUDEDIR}
+ cd ${.CURDIR}/../cddl/contrib/opensolaris/lib/libnvpair; \
+ ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 libnvpair.h \
+ ${DESTDIR}${INCLUDEDIR}
+ cd ${.CURDIR}/../sys/cddl/contrib/opensolaris/uts/common/sys; \
+ ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 nvpair.h \
+ ${DESTDIR}${INCLUDEDIR}/sys
+.endif
symlinks: .PHONY .META
@${ECHO} "Setting up symlinks to kernel source tree..."
@@ -238,7 +256,7 @@ symlinks: .PHONY .META
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \
done
.endfor
-.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/nand:Ndev/pci}
+.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/nand:Ndev/pci}
cd ${.CURDIR}/../sys/$i; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \
@@ -266,6 +284,11 @@ symlinks: .PHONY .META
${DESTDIR}${INCLUDEDIR}/dev/nand; \
done
.endif
+ cd ${.CURDIR}/../sys/dev/evdev; \
+ for h in input.h input-event-codes.h uinput.h; do \
+ ln -fs ../../../../sys/dev/evdev/$$h \
+ ${DESTDIR}${INCLUDEDIR}/dev/evdev; \
+ done
cd ${.CURDIR}/../sys/dev/pci; \
for h in pcireg.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/pci/$$h \
diff --git a/include/search.h b/include/search.h
index 4c1f534..068446f 100644
--- a/include/search.h
+++ b/include/search.h
@@ -34,16 +34,18 @@ typedef enum {
} VISIT;
#ifdef _SEARCH_PRIVATE
-typedef struct node {
- void *key;
- struct node *llink, *rlink;
- signed char balance;
-} node_t;
+typedef struct __posix_tnode {
+ void *key;
+ struct __posix_tnode *llink, *rlink;
+ signed char balance;
+} posix_tnode;
struct que_elem {
struct que_elem *next;
struct que_elem *prev;
};
+#else
+typedef void posix_tnode;
#endif
#if __BSD_VISIBLE
@@ -62,12 +64,15 @@ void *lfind(const void *, const void *, size_t *, size_t,
void *lsearch(const void *, void *, size_t *, size_t,
int (*)(const void *, const void *));
void remque(void *);
-void *tdelete(const void * __restrict, void ** __restrict,
+void *tdelete(const void * __restrict, posix_tnode ** __restrict,
int (*)(const void *, const void *));
-void *tfind(const void *, void * const *,
+posix_tnode *
+ tfind(const void *, posix_tnode * const *,
int (*)(const void *, const void *));
-void *tsearch(const void *, void **, int (*)(const void *, const void *));
-void twalk(const void *, void (*)(const void *, VISIT, int));
+posix_tnode *
+ tsearch(const void *, posix_tnode **,
+ int (*)(const void *, const void *));
+void twalk(const posix_tnode *, void (*)(const posix_tnode *, VISIT, int));
#if __BSD_VISIBLE
int hcreate_r(size_t, struct hsearch_data *);
diff --git a/lib/libc/db/btree/bt_close.c b/lib/libc/db/btree/bt_close.c
index 1f85992..f1e7c8d 100644
--- a/lib/libc/db/btree/bt_close.c
+++ b/lib/libc/db/btree/bt_close.c
@@ -134,7 +134,8 @@ __bt_sync(const DB *dbp, u_int flags)
return (RET_ERROR);
}
- if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED))
+ if (F_ISSET(t, B_INMEM | B_RDONLY) ||
+ !F_ISSET(t, B_MODIFIED | B_METADIRTY))
return (RET_SUCCESS);
if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
diff --git a/lib/libc/stdlib/tdelete.c b/lib/libc/stdlib/tdelete.c
index ff63576..38b2bd7 100644
--- a/lib/libc/stdlib/tdelete.c
+++ b/lib/libc/stdlib/tdelete.c
@@ -46,9 +46,9 @@ __FBSDID("$FreeBSD$");
* that we won't need to perform any rotations above \
* this point. In this case rotations are always \
* capable of keeping the subtree in balance. Make \
- * this the base node and reset the path. \
+ * this the root node and reset the path. \
*/ \
- base = leaf; \
+ rootp = leaf; \
path_init(&path); \
} \
path_taking_left(&path); \
@@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$");
#define GO_RIGHT() do { \
if ((*leaf)->balance == 0 || \
((*leaf)->balance > 0 && (*leaf)->llink->balance == 0)) { \
- base = leaf; \
+ rootp = leaf; \
path_init(&path); \
} \
path_taking_right(&path); \
@@ -67,18 +67,16 @@ __FBSDID("$FreeBSD$");
} while (0)
void *
-tdelete(const void *restrict key, void **restrict rootp,
+tdelete(const void *restrict key, posix_tnode **restrict rootp,
int (*compar)(const void *, const void *))
{
struct path path;
- node_t *root, **base, **leaf, *old, **n, *x, *y, *z;
- void *result;
+ posix_tnode **leaf, *old, **n, *x, *y, *z, *result;
int cmp;
/* POSIX requires that tdelete() returns NULL if rootp is NULL. */
if (rootp == NULL)
return (NULL);
- root = *rootp;
/*
* Find the leaf that needs to be removed. Return if we cannot
@@ -86,19 +84,18 @@ tdelete(const void *restrict key, void **restrict rootp,
* to get to the node, as we will need it to adjust the
* balances.
*/
- result = (void *)1;
+ result = (posix_tnode *)1;
path_init(&path);
- base = &root;
- leaf = &root;
+ leaf = rootp;
for (;;) {
if (*leaf == NULL)
return (NULL);
cmp = compar(key, (*leaf)->key);
if (cmp < 0) {
- result = &(*leaf)->key;
+ result = *leaf;
GO_LEFT();
} else if (cmp > 0) {
- result = &(*leaf)->key;
+ result = *leaf;
GO_RIGHT();
} else {
break;
@@ -134,7 +131,7 @@ tdelete(const void *restrict key, void **restrict rootp,
* and left-left case that only exists when deleting. Hence the
* duplication of code.
*/
- for (n = base; n != leaf;) {
+ for (n = rootp; n != leaf;) {
if (path_took_left(&path)) {
x = *n;
if (x->balance < 0) {
@@ -207,6 +204,5 @@ tdelete(const void *restrict key, void **restrict rootp,
}
/* Return the parent of the old entry. */
- *rootp = root;
return (result);
}
diff --git a/lib/libc/stdlib/tfind.c b/lib/libc/stdlib/tfind.c
index 0ad391e..afcbc16 100644
--- a/lib/libc/stdlib/tfind.c
+++ b/lib/libc/stdlib/tfind.c
@@ -4,8 +4,6 @@
* Tree search generalized from Knuth (6.2.2) Algorithm T just like
* the AT&T man page says.
*
- * The node_t structure is for internal use only, lint doesn't grok it.
- *
* Written by reading the System V Interface Definition, not the code.
*
* Totally public domain.
@@ -29,11 +27,10 @@ __FBSDID("$FreeBSD$");
* vkey - key to be found
* vrootp - address of the tree root
*/
-void *
-tfind(const void *vkey, void * const *vrootp,
+posix_tnode *
+tfind(const void *vkey, posix_tnode * const *rootp,
int (*compar)(const void *, const void *))
{
- node_t **rootp = (node_t **)vrootp;
if (rootp == NULL)
return NULL;
diff --git a/lib/libc/stdlib/tsearch.3 b/lib/libc/stdlib/tsearch.3
index 2205f7e..493eff2 100644
--- a/lib/libc/stdlib/tsearch.3
+++ b/lib/libc/stdlib/tsearch.3
@@ -27,7 +27,7 @@
.\" OpenBSD: tsearch.3,v 1.2 1998/06/21 22:13:49 millert Exp
.\" $FreeBSD$
.\"
-.Dd December 6, 2015
+.Dd October 9, 2016
.Dt TSEARCH 3
.Os
.Sh NAME
@@ -36,13 +36,13 @@
.Sh SYNOPSIS
.In search.h
.Ft void *
-.Fn tdelete "const void * restrict key" "void ** restrict rootp" "int (*compar) (const void *, const void *)"
-.Ft void *
-.Fn tfind "const void *key" "void * const *rootp" "int (*compar) (const void *, const void *)"
-.Ft void *
-.Fn tsearch "const void *key" "void **rootp" "int (*compar) (const void *, const void *)"
+.Fn tdelete "const void * restrict key" "posix_tnode ** restrict rootp" "int (*compar) (const void *, const void *)"
+.Ft posix_tnode *
+.Fn tfind "const void *key" "posix_tnode * const *rootp" "int (*compar) (const void *, const void *)"
+.Ft posix_tnode *
+.Fn tsearch "const void *key" "posix_tnode **rootp" "int (*compar) (const void *, const void *)"
.Ft void
-.Fn twalk "const void *root" "void (*action) (const void *, VISIT, int)"
+.Fn twalk "const posix_tnode *root" "void (*action) (const posix_tnode *, VISIT, int)"
.Sh DESCRIPTION
The
.Fn tdelete ,
@@ -134,3 +134,18 @@ function returns no value.
.Xr bsearch 3 ,
.Xr hsearch 3 ,
.Xr lsearch 3
+.Sh STANDARDS
+These functions conform to
+.St -p1003.1-2008 .
+.Pp
+The
+.Fa posix_tnode
+type is not part of
+.St -p1003.1-2008 ,
+but is expected to be standardized by future versions of the standard.
+It is defined as
+.Fa void
+for source-level compatibility.
+Using
+.Fa posix_tnode
+makes distinguishing between nodes and keys easier.
diff --git a/lib/libc/stdlib/tsearch.c b/lib/libc/stdlib/tsearch.c
index b96a275..a15c2c2 100644
--- a/lib/libc/stdlib/tsearch.c
+++ b/lib/libc/stdlib/tsearch.c
@@ -32,18 +32,17 @@ __FBSDID("$FreeBSD$");
#include "tsearch_path.h"
-void *
-tsearch(const void *key, void **rootp,
+posix_tnode *
+tsearch(const void *key, posix_tnode **rootp,
int (*compar)(const void *, const void *))
{
struct path path;
- node_t *root, **base, **leaf, *result, *n, *x, *y, *z;
+ posix_tnode **leaf, *result, *n, *x, *y, *z;
int cmp;
/* POSIX requires that tsearch() returns NULL if rootp is NULL. */
if (rootp == NULL)
- return (NULL);
- root = *rootp;
+ return (NULL);
/*
* Find the leaf where the new key needs to be inserted. Return
@@ -52,8 +51,7 @@ tsearch(const void *key, void **rootp,
* balances.
*/
path_init(&path);
- base = &root;
- leaf = &root;
+ leaf = rootp;
while (*leaf != NULL) {
if ((*leaf)->balance != 0) {
/*
@@ -62,9 +60,9 @@ tsearch(const void *key, void **rootp,
* need to perform any rotations above this
* point. In this case rotations are always
* capable of keeping the subtree in balance.
- * Make this the base node and reset the path.
+ * Make this the root node and reset the path.
*/
- base = leaf;
+ rootp = leaf;
path_init(&path);
}
cmp = compar(key, (*leaf)->key);
@@ -75,7 +73,7 @@ tsearch(const void *key, void **rootp,
path_taking_right(&path);
leaf = &(*leaf)->rlink;
} else {
- return (&(*leaf)->key);
+ return (*leaf);
}
}
@@ -94,7 +92,7 @@ tsearch(const void *key, void **rootp,
* have a balance of zero, meaning that these nodes will not get
* out of balance.
*/
- for (n = *base; n != *leaf;) {
+ for (n = *rootp; n != *leaf;) {
if (path_took_left(&path)) {
n->balance += 1;
n = n->llink;
@@ -106,10 +104,10 @@ tsearch(const void *key, void **rootp,
/*
* Adjusting the balances may have pushed the balance of the
- * base node out of range. Perform a rotation to bring the
+ * root node out of range. Perform a rotation to bring the
* balance back in range.
*/
- x = *base;
+ x = *rootp;
if (x->balance > 1) {
y = x->llink;
if (y->balance < 0) {
@@ -129,7 +127,7 @@ tsearch(const void *key, void **rootp,
z->llink = y;
x->llink = z->rlink;
z->rlink = x;
- *base = z;
+ *rootp = z;
x->balance = z->balance > 0 ? -1 : 0;
y->balance = z->balance < 0 ? 1 : 0;
@@ -146,7 +144,7 @@ tsearch(const void *key, void **rootp,
*/
x->llink = y->rlink;
y->rlink = x;
- *base = y;
+ *rootp = y;
x->balance = 0;
y->balance = 0;
@@ -165,12 +163,12 @@ tsearch(const void *key, void **rootp,
* / \ A B C D
* B C
*/
- node_t *z = y->llink;
+ posix_tnode *z = y->llink;
x->rlink = z->llink;
z->llink = x;
y->llink = z->rlink;
z->rlink = y;
- *base = z;
+ *rootp = z;
x->balance = z->balance < 0 ? 1 : 0;
y->balance = z->balance > 0 ? -1 : 0;
@@ -187,7 +185,7 @@ tsearch(const void *key, void **rootp,
*/
x->rlink = y->llink;
y->llink = x;
- *base = y;
+ *rootp = y;
x->balance = 0;
y->balance = 0;
@@ -195,6 +193,5 @@ tsearch(const void *key, void **rootp,
}
/* Return the new entry. */
- *rootp = root;
- return (&result->key);
+ return (result);
}
diff --git a/lib/libc/stdlib/twalk.c b/lib/libc/stdlib/twalk.c
index 7acee41..4f999b4 100644
--- a/lib/libc/stdlib/twalk.c
+++ b/lib/libc/stdlib/twalk.c
@@ -4,8 +4,6 @@
* Tree search generalized from Knuth (6.2.2) Algorithm T just like
* the AT&T man page says.
*
- * The node_t structure is for internal use only, lint doesn't grok it.
- *
* Written by reading the System V Interface Definition, not the code.
*
* Totally public domain.
@@ -23,12 +21,11 @@ __FBSDID("$FreeBSD$");
#include <search.h>
#include <stdlib.h>
-typedef void (*cmp_fn_t)(const void *, VISIT, int);
+typedef void (*cmp_fn_t)(const posix_tnode *, VISIT, int);
/* Walk the nodes of a tree */
static void
-trecurse(const node_t *root, /* Root of the tree to be walked */
- cmp_fn_t action, int level)
+trecurse(const posix_tnode *root, cmp_fn_t action, int level)
{
if (root->llink == NULL && root->rlink == NULL)
@@ -46,7 +43,7 @@ trecurse(const node_t *root, /* Root of the tree to be walked */
/* Walk the nodes of a tree */
void
-twalk(const void *vroot, cmp_fn_t action) /* Root of the tree to be walked */
+twalk(const posix_tnode *vroot, cmp_fn_t action)
{
if (vroot != NULL && action != NULL)
trecurse(vroot, action, 0);
diff --git a/lib/libc/sys/getrlimit.2 b/lib/libc/sys/getrlimit.2
index 1fc3656..1ac01d3 100644
--- a/lib/libc/sys/getrlimit.2
+++ b/lib/libc/sys/getrlimit.2
@@ -28,7 +28,7 @@
.\" @(#)getrlimit.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd August 19, 2015
+.Dd September 30, 2016
.Dt GETRLIMIT 2
.Os
.Sh NAME
@@ -137,7 +137,7 @@ For example, if the RSS hard limit is exceeded, nothing happens.
.Pp
The
.Vt rlimit
-structure is used to specify the hard and soft limits on a resource,
+structure is used to specify the hard and soft limits on a resource.
.Bd -literal -offset indent
struct rlimit {
rlim_t rlim_cur; /* current (soft) limit */
@@ -183,9 +183,9 @@ soft limit will cause the write to fail and a signal
to be
generated; this normally terminates the process, but may be caught.
When
-the soft cpu time limit is exceeded, a signal
+the soft cpu time limit is exceeded, a
.Dv SIGXCPU
-is sent to the
+signal is sent to the
offending process.
.Pp
When most operations would allocate more virtual memory than allowed by the
@@ -198,7 +198,9 @@ A notable exception is stack extension, described above.
If stack extension would allocate more virtual memory than allowed by the soft
limit of
.Dv RLIMIT_AS ,
-the signal SIGSEGV will be delivered.
+a
+.Dv SIGSEGV
+signal will be delivered.
The caller is free to raise the soft address space limit up to the hard limit
and retry the allocation.
.Sh RETURN VALUES
diff --git a/lib/libc/sys/sigaction.2 b/lib/libc/sys/sigaction.2
index 5c784f6..00d8215 100644
--- a/lib/libc/sys/sigaction.2
+++ b/lib/libc/sys/sigaction.2
@@ -28,7 +28,7 @@
.\" From: @(#)sigaction.2 8.2 (Berkeley) 4/3/94
.\" $FreeBSD$
.\"
-.Dd September 6, 2013
+.Dd September 30, 2016
.Dt SIGACTION 2
.Os
.Sh NAME
@@ -307,46 +307,38 @@ The following is a list of all signals
with names as in the include file
.In signal.h :
.Bl -column SIGVTALARMXX "create core imagexxx"
-.It Sy "NAME Default Action Description"
-.It Dv SIGHUP No " terminate process" " terminal line hangup"
-.It Dv SIGINT No " terminate process" " interrupt program"
-.It Dv SIGQUIT No " create core image" " quit program"
-.It Dv SIGILL No " create core image" " illegal instruction"
-.It Dv SIGTRAP No " create core image" " trace trap"
-.It Dv SIGABRT No " create core image" Ta Xr abort 3
-call (formerly
-.Dv SIGIOT )
-.It Dv SIGEMT No " create core image" " emulate instruction executed"
-.It Dv SIGFPE No " create core image" " floating-point exception"
-.It Dv SIGKILL No " terminate process" " kill program"
-.It Dv SIGBUS No " create core image" " bus error"
-.It Dv SIGSEGV No " create core image" " segmentation violation"
-.It Dv SIGSYS No " create core image" " non-existent system call invoked"
-.It Dv SIGPIPE No " terminate process" " write on a pipe with no reader"
-.It Dv SIGALRM No " terminate process" " real-time timer expired"
-.It Dv SIGTERM No " terminate process" " software termination signal"
-.It Dv SIGURG No " discard signal" " urgent condition present on socket"
-.It Dv SIGSTOP No " stop process" " stop (cannot be caught or ignored)"
-.It Dv SIGTSTP No " stop process" " stop signal generated from keyboard"
-.It Dv SIGCONT No " discard signal" " continue after stop"
-.It Dv SIGCHLD No " discard signal" " child status has changed"
-.It Dv SIGTTIN No " stop process" " background read attempted from control terminal"
-.It Dv SIGTTOU No " stop process" " background write attempted to control terminal"
-.It Dv SIGIO No " discard signal" Tn " I/O"
-is possible on a descriptor (see
-.Xr fcntl 2 )
-.It Dv SIGXCPU No " terminate process" " cpu time limit exceeded (see"
-.Xr setrlimit 2 )
-.It Dv SIGXFSZ No " terminate process" " file size limit exceeded (see"
-.Xr setrlimit 2 )
-.It Dv SIGVTALRM No " terminate process" " virtual time alarm (see"
-.Xr setitimer 2 )
-.It Dv SIGPROF No " terminate process" " profiling timer alarm (see"
-.Xr setitimer 2 )
-.It Dv SIGWINCH No " discard signal" " Window size change"
-.It Dv SIGINFO No " discard signal" " status request from keyboard"
-.It Dv SIGUSR1 No " terminate process" " User defined signal 1"
-.It Dv SIGUSR2 No " terminate process" " User defined signal 2"
+.It Sy NAME Ta Sy Default Action Ta Sy Description
+.It Dv SIGHUP Ta terminate process Ta terminal line hangup
+.It Dv SIGINT Ta terminate process Ta interrupt program
+.It Dv SIGQUIT Ta create core image Ta quit program
+.It Dv SIGILL Ta create core image Ta illegal instruction
+.It Dv SIGTRAP Ta create core image Ta trace trap
+.It Dv SIGABRT Ta create core image Ta Xr abort 3 call (formerly Dv SIGIOT )
+.It Dv SIGEMT Ta create core image Ta emulate instruction executed
+.It Dv SIGFPE Ta create core image Ta floating-point exception
+.It Dv SIGKILL Ta terminate process Ta kill program
+.It Dv SIGBUS Ta create core image Ta bus error
+.It Dv SIGSEGV Ta create core image Ta segmentation violation
+.It Dv SIGSYS Ta create core image Ta non-existent system call invoked
+.It Dv SIGPIPE Ta terminate process Ta write on a pipe with no reader
+.It Dv SIGALRM Ta terminate process Ta real-time timer expired
+.It Dv SIGTERM Ta terminate process Ta software termination signal
+.It Dv SIGURG Ta discard signal Ta urgent condition present on socket
+.It Dv SIGSTOP Ta stop process Ta stop (cannot be caught or ignored)
+.It Dv SIGTSTP Ta stop process Ta stop signal generated from keyboard
+.It Dv SIGCONT Ta discard signal Ta continue after stop
+.It Dv SIGCHLD Ta discard signal Ta child status has changed
+.It Dv SIGTTIN Ta stop process Ta background read attempted from control terminal
+.It Dv SIGTTOU Ta stop process Ta background write attempted to control terminal
+.It Dv SIGIO Ta discard signal Ta I/O is possible on a descriptor (see Xr fcntl 2 )
+.It Dv SIGXCPU Ta terminate process Ta cpu time limit exceeded (see Xr setrlimit 2 )
+.It Dv SIGXFSZ Ta terminate process Ta file size limit exceeded (see Xr setrlimit 2 )
+.It Dv SIGVTALRM Ta terminate process Ta virtual time alarm (see Xr setitimer 2 )
+.It Dv SIGPROF Ta terminate process Ta profiling timer alarm (see Xr setitimer 2 )
+.It Dv SIGWINCH Ta discard signal Ta window size change
+.It Dv SIGINFO Ta discard signal Ta status request from keyboard
+.It Dv SIGUSR1 Ta terminate process Ta user defined signal 1
+.It Dv SIGUSR2 Ta terminate process Ta user defined signal 2
.El
.Sh NOTE
The
@@ -739,6 +731,8 @@ or
.Xr kill 1 ,
.Xr kill 2 ,
.Xr ptrace 2 ,
+.Xr setitimer 2 ,
+.Xr setrlimit 2 ,
.Xr sigaltstack 2 ,
.Xr sigpending 2 ,
.Xr sigprocmask 2 ,
diff --git a/lib/libc/tests/iconv/Makefile b/lib/libc/tests/iconv/Makefile
index e6ae03e..635c26c 100644
--- a/lib/libc/tests/iconv/Makefile
+++ b/lib/libc/tests/iconv/Makefile
@@ -1,7 +1,5 @@
# $FreeBSD$
-PACKAGE= tests
-
TESTSDIR= ${TESTSBASE}/lib/libc/iconv
ATF_TESTS_C+= iconvctl_test
diff --git a/lib/libc/tests/stdio/printbasic_test.c b/lib/libc/tests/stdio/printbasic_test.c
index 376981e..bebb734 100644
--- a/lib/libc/tests/stdio/printbasic_test.c
+++ b/lib/libc/tests/stdio/printbasic_test.c
@@ -80,7 +80,7 @@ _testfmt(const char *result, const char *argstr, const char *fmt,...)
vsnprintf(s, sizeof(s), fmt, ap);
if (strcmp(result, s) != 0) {
atf_tc_fail(
- "printf(\"%s\", %s) ==> [%s], expected [%s]\n",
+ "printf(\"%s\", %s) ==> [%s], expected [%s]",
fmt, argstr, s, result);
}
@@ -91,7 +91,7 @@ _testfmt(const char *result, const char *argstr, const char *fmt,...)
vswprintf(ws, sizeof(ws) / sizeof(ws[0]), wfmt, ap2);
if (wcscmp(wresult, ws) != 0) {
atf_tc_fail(
- "wprintf(\"%ls\", %s) ==> [%ls], expected [%ls]\n",
+ "wprintf(\"%ls\", %s) ==> [%ls], expected [%ls]",
wfmt, argstr, ws, wresult);
}
va_end(ap);
diff --git a/lib/libc/tests/stdio/printfloat_test.c b/lib/libc/tests/stdio/printfloat_test.c
index 2319747..974374f 100644
--- a/lib/libc/tests/stdio/printfloat_test.c
+++ b/lib/libc/tests/stdio/printfloat_test.c
@@ -72,7 +72,7 @@ _testfmt(const char *result, const char *argstr, const char *fmt,...)
vsnprintf(s, sizeof(s), fmt, ap);
if (strcmp(result, s) != 0) {
atf_tc_fail(
- "printf(\"%s\", %s) ==> [%s], expected [%s]\n",
+ "printf(\"%s\", %s) ==> [%s], expected [%s]",
fmt, argstr, s, result);
}
@@ -83,7 +83,7 @@ _testfmt(const char *result, const char *argstr, const char *fmt,...)
vswprintf(ws, sizeof(ws) / sizeof(ws[0]), wfmt, ap2);
if (wcscmp(wresult, ws) != 0) {
atf_tc_fail(
- "wprintf(\"%ls\", %s) ==> [%ls], expected [%ls]\n",
+ "wprintf(\"%ls\", %s) ==> [%ls], expected [%ls]",
wfmt, argstr, ws, wresult);
}
va_end(ap);
diff --git a/lib/libc/tests/stdlib/tsearch_test.c b/lib/libc/tests/stdlib/tsearch_test.c
index b08fd94..88c62f5 100644
--- a/lib/libc/tests/stdlib/tsearch_test.c
+++ b/lib/libc/tests/stdlib/tsearch_test.c
@@ -34,7 +34,7 @@ __FBSDID("$FreeBSD$");
/* Validates the integrity of an AVL tree. */
static inline unsigned int
-tnode_assert(const node_t *n)
+tnode_assert(const posix_tnode *n)
{
unsigned int height_left, height_right;
int balance;
@@ -79,7 +79,7 @@ ATF_TC_BODY(tsearch_test, tc)
keys[i] = i;
/* Apply random operations on a binary tree and check the results. */
- void *root = NULL;
+ posix_tnode *root = NULL;
bool present[NKEYS] = {};
for (int i = 0; i < NKEYS * 10; ++i) {
int key = nrand48(random_state) % NKEYS;
diff --git a/lib/libc/tests/sys/Makefile b/lib/libc/tests/sys/Makefile
index 6711287..08c4618 100644
--- a/lib/libc/tests/sys/Makefile
+++ b/lib/libc/tests/sys/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+PACKAGE= tests
+
.include <bsd.own.mk>
ATF_TESTS_C+= queue_test
diff --git a/lib/libdevdctl/consumer.cc b/lib/libdevdctl/consumer.cc
index e769894..a9949a6 100644
--- a/lib/libdevdctl/consumer.cc
+++ b/lib/libdevdctl/consumer.cc
@@ -108,11 +108,9 @@ Consumer::ConnectToDevd()
strlcpy(devdAddr.sun_path, s_devdSockPath, sizeof(devdAddr.sun_path));
sLen = SUN_LEN(&devdAddr);
- m_devdSockFD = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+ m_devdSockFD = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 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);
diff --git a/lib/libunbound/Makefile b/lib/libunbound/Makefile
index aeb59095..a30bfc7 100644
--- a/lib/libunbound/Makefile
+++ b/lib/libunbound/Makefile
@@ -6,7 +6,7 @@ LDNSDIR= ${.CURDIR}/../../contrib/ldns
UNBOUNDDIR= ${.CURDIR}/../../contrib/unbound
# Hold my beer and watch this
-.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/dns64 ${UNBOUNDDIR}/iterator ${UNBOUNDDIR}/sldns ${UNBOUNDDIR}/libunbound ${UNBOUNDDIR}/services ${UNBOUNDDIR}/services/cache ${UNBOUNDDIR}/util ${UNBOUNDDIR}/util/data ${UNBOUNDDIR}/util/storage ${UNBOUNDDIR}/validator
+.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/cachedb ${UNBOUNDDIR}/dns64 ${UNBOUNDDIR}/iterator ${UNBOUNDDIR}/sldns ${UNBOUNDDIR}/libunbound ${UNBOUNDDIR}/services ${UNBOUNDDIR}/services/cache ${UNBOUNDDIR}/util ${UNBOUNDDIR}/util/data ${UNBOUNDDIR}/util/storage ${UNBOUNDDIR}/validator
LIB= unbound
PRIVATELIB=
@@ -14,19 +14,19 @@ PACKAGE= unbound
CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR} -I${.OBJDIR}
-SRCS= alloc.c as112.c autotrust.c config_file.c configlexer.l configparser.y \
- context.c dname.c dns.c dns64.c dnstree.c fptr_wlist.c infra.c \
- iter_delegpt.c iter_donotq.c iter_fwd.c iter_hints.c iter_priv.c \
- iter_resptype.c iter_scrub.c iter_utils.c iterator.c keyraw.c \
- libunbound.c libworker.c listen_dnsport.c localzone.c locks.c log.c \
- lookup3.c lruhash.c mesh.c mini_event.c modstack.c module.c \
- msgencode.c msgparse.c msgreply.c net_help.c netevent.c \
- outbound_list.c outside_network.c packed_rrset.c parse.c \
+SRCS= alloc.c as112.c autotrust.c cachedb.c config_file.c configlexer.l \
+ configparser.y context.c dname.c dns.c dns64.c dnstree.c \
+ fptr_wlist.c infra.c iter_delegpt.c iter_donotq.c iter_fwd.c \
+ iter_hints.c iter_priv.c iter_resptype.c iter_scrub.c iter_utils.c \
+ iterator.c keyraw.c libunbound.c libworker.c listen_dnsport.c \
+ localzone.c locks.c log.c lookup3.c lruhash.c mesh.c mini_event.c \
+ modstack.c module.c msgencode.c msgparse.c msgreply.c net_help.c \
+ netevent.c outbound_list.c outside_network.c packed_rrset.c parse.c \
parseutil.c random.c rbtree.c regional.c rrdef.c rrset.c rtt.c \
- sbuffer.c slabhash.c str2wire.c timehist.c tube.c val_anchor.c \
- val_kcache.c val_kentry.c val_neg.c val_nsec.c val_nsec3.c \
- val_secalgo.c val_sigcrypt.c val_utils.c validator.c \
- winsock_event.c wire2str.c
+ sbuffer.c slabhash.c str2wire.c timehist.c tube.c \
+ ub_event_pluggable.c val_anchor.c val_kcache.c val_kentry.c \
+ val_neg.c val_nsec.c val_nsec3.c val_secalgo.c val_sigcrypt.c \
+ val_utils.c validator.c winsock_event.c wire2str.c
WARNS?= 3
diff --git a/libexec/atf/atf-check/Makefile b/libexec/atf/atf-check/Makefile
index 5bef488..ca3c2ef 100644
--- a/libexec/atf/atf-check/Makefile
+++ b/libexec/atf/atf-check/Makefile
@@ -28,7 +28,7 @@
.include <src.opts.mk>
.include <bsd.init.mk>
-ATF= ${.CURDIR:H:H:H}/contrib/atf
+ATF= ${SRCTOP}/contrib/atf
.PATH: ${ATF}/atf-sh
PROG_CXX= atf-check
diff --git a/libexec/atf/atf-sh/Makefile b/libexec/atf/atf-sh/Makefile
index f00683f..42cf5a5 100644
--- a/libexec/atf/atf-sh/Makefile
+++ b/libexec/atf/atf-sh/Makefile
@@ -28,7 +28,7 @@
.include <src.opts.mk>
.include <bsd.init.mk>
-ATF= ${.CURDIR:H:H:H}/contrib/atf
+ATF= ${SRCTOP}/contrib/atf
.PATH: ${ATF}/atf-sh
PROG_CXX= atf-sh
diff --git a/libexec/ypxfr/ypxfr_getmap.c b/libexec/ypxfr/ypxfr_getmap.c
index 458971f..1bde10e 100644
--- a/libexec/ypxfr/ypxfr_getmap.c
+++ b/libexec/ypxfr/ypxfr_getmap.c
@@ -43,8 +43,8 @@ __FBSDID("$FreeBSD$");
extern bool_t xdr_ypresp_all_seq(XDR *, unsigned long *);
-static int (*ypresp_allfn)();
-static void *ypresp_data;
+extern int (*ypresp_allfn)();
+extern void *ypresp_data;
extern DB *specdbp;
extern enum ypstat yp_errno;
diff --git a/release/doc/en_US.ISO8859-1/errata/article.xml b/release/doc/en_US.ISO8859-1/errata/article.xml
index 8f02af5..b27224f 100644
--- a/release/doc/en_US.ISO8859-1/errata/article.xml
+++ b/release/doc/en_US.ISO8859-1/errata/article.xml
@@ -97,8 +97,8 @@
<listitem>
<para>An issue was discovered with Amazon&reg; EC2&trade;
images which would cause the virtual machine to hang during
- boot when upgrading from previous FreeBSD versions. New
- EC2&trade; installations are not affected, but exisiting
+ boot when upgrading from previous FreeBSD versions. New
+ EC2&trade; installations are not affected, but existing
installations running earlier releases are advised to wait
until the issue is resolved in an Errata Notice before
upgrading. An Errata Notice to address this is planned
@@ -198,6 +198,68 @@ boot</screen>
</listitem>
</itemizedlist>
</listitem>
+
+ <listitem>
+ <para revision="293860">[2016-10-20] Several recent Dell
+ systems fail to find a bootable disk when the system boots
+ in Legacy/BIOS/CSM mode, the boot disk is partitioned with
+ <acronym>GPT</acronym>, and the Active flag in the
+ Protective <acronym>MBR</acronym> is not set. To work
+ around this issue, either configure the system to boot in
+ <acronym>UEFI</acronym> mode, or choose the &quot;GPT
+ + Active&quot; scheme.</para>
+ </listitem>
+
+ <listitem>
+ <para>[2016-10-21] Support for <literal>sha512</literal> and
+ <literal>skein</literal> checksumming has been added to the
+ <acronym>ZFS</acronym> filesystem. This was not mentioned
+ in the release notes.</para>
+
+ <para>Systems being upgraded from earlier &os; releases with
+ <acronym>ZFS</acronym> will see a message in <literal>zpool
+ status</literal> output noting the pool is not at the
+ latest version, and some features may not be enabled.
+ Additional instructions on how to update
+ <acronym>ZFS</acronym> pools to the latest version and
+ update the boot blocks for all boot drives in the pool will
+ also be provided in the output.</para>
+
+ <para>This information is also documented in
+ <filename>/usr/src/UPDATING</filename>, which is included if
+ the <literal>src</literal> component is selected during
+ installation.</para>
+ </listitem>
+
+ <listitem>
+ <para>[2016-10-21] The size of the <acronym>GPT</acronym>
+ enabled <acronym>ZFS</acronym> boot blocks
+ (<filename>/boot/gptzfsboot</filename>) has increased past
+ 64K. Systems upgraded from older releases may experience
+ a problem where the size of the existing
+ &quot;freebsd-boot&quot; partition is too small to hold the
+ new <filename>gptzfsboot</filename>.</para>
+
+ <para>Systems where the boot partition is immediately followed
+ by the swap partition, such as those installed via
+ &man.bsdinstall.8;, can resize the swap partition slightly
+ using the &man.gpart.8; <literal>resize</literal> command,
+ so space can be reclaimed to increase the size of the
+ freebsd-boot partition.</para>
+ </listitem>
+
+ <listitem>
+ <para>[2016-10-21] Due to a bug in earlier versions of
+ &man.clang.1; that is difficult to work around in the
+ upgrade process, to upgrade the system from sources via
+ buildworld to -CURRENT or &release;, it is necessary to
+ upgrade machines running 9.x to at least revision r286035,
+ or machines running 10.x to revision r286033. Source-based
+ upgrades from 10.3-RELEASE are not affected. This differs
+ from the historical situation where one could generally
+ upgrade from anywhere on earlier stable branches, so caution
+ should be exercised.</para>
+ </listitem>
</itemizedlist>
</sect1>
diff --git a/release/doc/share/xml/errata.xml b/release/doc/share/xml/errata.xml
index efc21a1..9cf8971 100644
--- a/release/doc/share/xml/errata.xml
+++ b/release/doc/share/xml/errata.xml
@@ -19,9 +19,10 @@
<tbody>
<row>
- <entry><para>No errata notices.</para></entry>
- <entry><para>&nbsp;</para></entry>
- <entry><para>&nbsp;</para></entry>
+ <entry><link
+ xlink:href="&security.url;/FreeBSD-EN-16:18.loader.asc">FreeBSD-EN-16:18.loader</link></entry>
+ <entry>25&nbsp;October&nbsp;2016</entry>
+ <entry><para>Loader may hang during boot</para></entry>
</row>
</tbody>
</tgroup>
diff --git a/release/doc/share/xml/security.xml b/release/doc/share/xml/security.xml
index 74a8cd7..5054271 100644
--- a/release/doc/share/xml/security.xml
+++ b/release/doc/share/xml/security.xml
@@ -19,9 +19,10 @@
<tbody>
<row>
- <entry><para>No advisories.</para></entry>
- <entry><para>&nbsp;</para></entry>
- <entry><para>&nbsp;</para></entry>
+ <entry><link
+ xlink:href="&security.url;/FreeBSD-SA-16:32.bhyve.asc">FreeBSD-SA-16:32.bhyve</link></entry>
+ <entry>25&nbsp;October&nbsp;2016</entry>
+ <entry><para>Privilege escalation vulnerability</para></entry>
</row>
</tbody>
</tgroup>
diff --git a/sbin/init/init.c b/sbin/init/init.c
index bda86b5..25ac2bd 100644
--- a/sbin/init/init.c
+++ b/sbin/init/init.c
@@ -870,6 +870,7 @@ single_user(void)
sigset_t mask;
const char *shell;
char *argv[2];
+ struct timeval tv, tn;
#ifdef SECURE
struct ttyent *typ;
struct passwd *pp;
@@ -884,8 +885,13 @@ single_user(void)
if (Reboot) {
/* Instead of going single user, let's reboot the machine */
sync();
- reboot(howto);
- _exit(0);
+ if (reboot(howto) == -1) {
+ emergency("reboot(%#x) failed, %s", howto,
+ strerror(errno));
+ _exit(1); /* panic and reboot */
+ }
+ warning("reboot(%#x) returned", howto);
+ _exit(0); /* panic as well */
}
shell = get_shell();
@@ -1002,7 +1008,14 @@ single_user(void)
* reboot(8) killed shell?
*/
warning("single user shell terminated.");
- sleep(STALL_TIMEOUT);
+ gettimeofday(&tv, NULL);
+ tn = tv;
+ tv.tv_sec += STALL_TIMEOUT;
+ while (tv.tv_sec > tn.tv_sec || (tv.tv_sec ==
+ tn.tv_sec && tv.tv_usec > tn.tv_usec)) {
+ sleep(1);
+ gettimeofday(&tn, NULL);
+ }
_exit(0);
} else {
warning("single user shell terminated, restarting");
diff --git a/sbin/mount_msdosfs/mount_msdosfs.8 b/sbin/mount_msdosfs/mount_msdosfs.8
index 3e4b08d..9f39ffb 100644
--- a/sbin/mount_msdosfs/mount_msdosfs.8
+++ b/sbin/mount_msdosfs/mount_msdosfs.8
@@ -142,15 +142,8 @@ If neither
nor
.Fl l
are given,
-.Nm
-searches the root directory of the file system to
-be mounted for any existing Win'95 long filenames.
-If no such entries are found, but short DOS filenames are found,
-.Fl s
-is the default.
-Otherwise
.Fl l
-is assumed.
+is the default.
.It Fl 9
Ignore the special Win'95 directory entries even
if deleting or renaming a file.
diff --git a/sbin/natd/natd.c b/sbin/natd/natd.c
index aa1628a..268850c 100644
--- a/sbin/natd/natd.c
+++ b/sbin/natd/natd.c
@@ -2006,7 +2006,7 @@ NewInstance(const char *name)
}
}
ninstance++;
- ip = calloc(sizeof *ip, 1);
+ ip = calloc(1, sizeof(*ip));
ip->name = strdup(name);
ip->la = LibAliasInit (ip->la);
ip->assignAliasAddr = 0;
diff --git a/share/misc/pci_vendors b/share/misc/pci_vendors
index 2bc34d3..3d9c83c 100644
--- a/share/misc/pci_vendors
+++ b/share/misc/pci_vendors
@@ -3,8 +3,8 @@
#
# List of PCI ID's
#
-# Version: 2016.10.03
-# Date: 2016-10-03 03:15:01
+# Version: 2016.10.20
+# Date: 2016-10-20 03:15:02
#
# Maintained by Albert Pool, Martin Mares, and other volunteers from
# the PCI ID Project at http://pci-ids.ucw.cz/.
@@ -245,8 +245,13 @@
0013 53c875a
1000 1000 LSI53C875A PCI to Ultra SCSI Controller
0014 MegaRAID Tri-Mode SAS3516
+ 1028 1fd4 PERC H745P MX
1d49 0602 ThinkSystem RAID 930-16i 4GB Flash PCIe 12Gb Adapter
0016 MegaRAID Tri-Mode SAS3508
+ 1028 1fc9 PERC H840 Adapter
+ 1028 1fcb PERC H740P Adapter
+ 1028 1fcd PERC H740P Mini
+ 1028 1fcf PERC H740P Mini
1d49 0601 ThinkSystem RAID 930-8i 2GB Flash PCIe 12Gb Adapter
1d49 0603 ThinkSystem RAID 930-24i 4GB Flash PCIe 12Gb Adapter
1d49 0604 ThinkSystem RAID 930-8e 4GB Flash PCIe 12Gb Adapter
@@ -376,6 +381,7 @@
1028 1f4d PERC FD33xS
1028 1f4f PERC H730P Slim
1028 1f54 PERC FD33xD
+ 1028 1fd1 PERC H730P MX
17aa 1052 ThinkServer RAID 720i
17aa 1053 ThinkServer RAID 720ix
1d49 0600 ThinkSystem RAID 730-8i 1GB Cache PCIe 12Gb Adapter
@@ -535,8 +541,11 @@
0097 SAS3008 PCI-Express Fusion-MPT SAS-3
1000 3090 SAS9311-8i
1000 30e0 SAS9300-8i
- 1028 1f45 12GB/s HBA internal
+ 1028 1f45 HBA330 Adapter
1028 1f46 12Gbps HBA
+ 1028 1f53 HBA330 Mini
+ 1028 1fd2 HBA330 MX
+ 1028 1fd3 HBA330 MMZ
00ab SAS3516 Fusion-MPT Tri-Mode RAID On Chip (ROC)
00ac SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC)
1d49 0201 ThinkSystem 9400-16i PCIe 12Gb HBA
@@ -1588,7 +1597,7 @@
1462 2938 Radeon R9 360 OEM
1462 3271 Radeon R9 360 OEM
1682 7360 Radeon R7 360
- 6660 Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330]
+ 6660 Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430]
1028 05ea Radeon HD 8670M
1028 06bf Radeon R5 M335
103c 1970 Radeon HD 8670M
@@ -1596,6 +1605,7 @@
103c 8136 Radeon R5 M330
17aa 3804 Radeon R5 M330
17aa 3809 Radeon R5 M330
+ 17aa 381a Radeon R5 M430
17aa 390c Radeon R5 M330
6663 Sun PRO [Radeon HD 8570A/8570M]
1025 0846 Radeon HD 8570A
@@ -2866,11 +2876,12 @@
174b e180 Radeon HD 7350
17af 3015 Radeon HD 7350
68fe Cedar LE
- 6900 Topaz XT [Radeon R7 M260/M265 / M340/M360]
+ 6900 Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445]
1025 1056 Radeon R7 M360 / R8 M365DX
1028 0640 Radeon R7 M260/M265
1028 0643 Radeon R7 M260/M265
1028 067f Radeon R7 M260
+ 1028 0767 Radeon R7 M445
1028 130a Radeon R7 M260
103c 2263 Radeon R7 M260
103c 2269 Radeon R7 M260
@@ -2881,6 +2892,7 @@
103c 80b5 Radeon R7 M360
103c 80b9 Radeon R7 M360
103c 811c Radeon R7 M340
+ 103c 8226 Radeon R7 M440
10cf 1906 Radeon R7 M260
1170 9979 Radeon R7 M360
1179 f903 Radeon R7 M260
@@ -2892,6 +2904,7 @@
17aa 5021 Radeon R7 M260
6901 Topaz PRO [Radeon R5 M255]
103c 1318 Radeon R6 M255DX
+ 6907 Meso XT [Radeon R5 M315]
6921 Amethyst XT [Radeon R9 M295X]
6929 Tonga XT GL [FirePro S7150]
692b Tonga PRO GL [FirePro W7100]
@@ -3349,7 +3362,7 @@
99a4 Trinity [Radeon HD 7400G]
aa00 R600 HDMI Audio [Radeon HD 2900 GT/PRO/XT]
aa01 RV635 HDMI Audio [Radeon HD 3650/3730/3750]
- aa08 RV630 HDMI Audio [Radeon HD 2600 Series]
+ aa08 RV630 HDMI Audio [Radeon HD 2600 PRO/XT / HD 3610]
aa10 RV610 HDMI Audio [Radeon HD 2350 PRO / 2400 PRO/XT / HD 3410]
174b aa10 Radeon HD 2400 PRO
18bc aa10 Radeon HD 2400 PRO
@@ -3369,10 +3382,10 @@
aa68 Cedar HDMI Audio [Radeon HD 5400/6300/7300 Series]
1028 aa68 XPS 8300
aa80 Cayman/Antilles HDMI Audio [Radeon HD 6930/6950/6970/6990]
- aa88 Barts HDMI Audio [Radeon HD 6800 Series]
+ aa88 Barts HDMI Audio [Radeon HD 6790/6850/6870 / 7720 OEM]
aa90 Turks HDMI Audio [Radeon HD 6500/6600 / 6700M Series]
1028 04a3 Precision M4600
- aa98 Caicos HDMI Audio [Radeon HD 6400 Series]
+ aa98 Caicos HDMI Audio [Radeon HD 6450 / 7450/8450/8490 OEM / R5 230/235/235X OEM]
174b aa98 Radeon HD 6450 1GB DDR3
aaa0 Tahiti HDMI Audio [Radeon HD 7870 XT / 7950/7970]
aab0 Cape Verde/Pitcairn HDMI Audio [Radeon HD 7700/7800 Series]
@@ -7347,6 +7360,7 @@
8533 PEX 8533 32-lane, 6-port PCI Express Switch
8547 PEX 8547 48-lane, 3-port PCI Express Switch
8548 PEX 8548 48-lane, 9-port PCI Express Switch
+ 8603 PEX 8603 3-lane, 3-Port PCI Express Gen 2 (5.0 GT/s) Switch
8604 PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch
8605 PEX 8605 PCI Express 4-port Gen2 Switch
8606 PEX 8606 6 Lane, 6 Port PCI Express Gen 2 (5.0 GT/s) Switch
@@ -17921,7 +17935,7 @@
1015 MT27710 Family [ConnectX-4 Lx]
1016 MT27710 Family [ConnectX-4 Lx Virtual Function]
1017 MT27800 Family [ConnectX-5]
- 1018 MT28800 Family [ConnectX-5 Virtual Function]
+ 1018 MT27800 Family [ConnectX-5 Virtual Function]
1019 MT28800 Family [ConnectX-5 Ex]
101a MT28800 Family [ConnectX-5 Ex Virtual Function]
101b MT28831
@@ -17932,6 +17946,7 @@
1020 MT28860
1021 MT28861
1974 MT28800 Family [ConnectX-5 PCIe Bridge]
+ 1975 MT416842 Family [BlueField SoC PCIe Bridge]
5274 MT21108 InfiniBridge
5a44 MT23108 InfiniHost
5a45 MT23108 [Infinihost HCA Flash Recovery]
@@ -17966,6 +17981,9 @@
7121 NPS-600 configuration and management interface
7122 NPS-600 network interface PF
7123 NPS-600 network interface VF
+ a2d0 MT416842
+ a2d1 MT416842
+ a2d3 MT416842 BlueField multicore SoC family VF
# SwitchX-2, 40GbE switch
c738 MT51136
c739 MT51136 GW
@@ -18638,7 +18656,12 @@
7018 AP408: 32-Channel Digital I/O Module
701a AP220-16 12-Bit, 16-Channel Analog Output Module
701b AP231-16 16-Bit, 16-Channel Analog Output Module
+ 7021 APA7-201 Reconfigurable Artix-7 FPGA module 48 TTL channels
+ 7022 APA7-202 Reconfigurable Artix-7 FPGA module 24 RS485 channels
+ 7023 APA7-203 Reconfigurable Artix-7 FPGA module 24 TTL & 12 RS485 channels
+ 7024 APA7-204 Reconfigurable Artix-7 FPGA module 24 LVDS channels
7042 AP482 Counter Timer Module with TTL Level Input/Output
+ 7043 AP483 Counter Timer Module with TTL Level and RS422 Input/Output
7044 AP484 Counter Timer Module with RS422 Input/Output
16da Advantech Co., Ltd.
0011 INES GPIB-PCI
@@ -18881,6 +18904,7 @@
0401 Datacenter Technologies QDF2400 PCI Express Root Port
17cc NetChip Technology, Inc
2280 USB 2.0
+17cd Cadence Design Systems, Inc.
17cf Z-Com, Inc.
17d3 Areca Technology Corp.
1110 ARC-1110 4-Port PCI-X to SATA RAID Controller
@@ -20290,7 +20314,8 @@
1432 8102 EN-8102P 10GbE Ethernet Adapter
1fc9 3015 Ethernet Adapter
4026 TN9610 10GbE SFP+ Ethernet Adapter
- 4027 TN9710 10GBase-T/NBASE-T Ethernet Adapter
+ 4027 TN9710P 10GBase-T/NBASE-T Ethernet Adapter
+ 4527 TN9710Q 5GBase-T/NBASE-T Ethernet Adapter
1fcc StreamLabs
f416 MS416
fb01 MH4LM
@@ -22295,6 +22320,7 @@
17aa 4007 82599ES 10-Gigabit SFI/SFP+ Network Connection
17aa 402b 82599ES 10Gb 2-port Server Adapter X520-DA2
17aa 402f FPGA Card XC7VX690T-3FFG1157E
+ 18d4 0c09 82599ES 10Gb 2-port SFP+ OCP Mezz Card MOP81-I-10GS2
1bd4 001b 10G SFP+ DP ER102Fi4 Rack Adapter
1bd4 002f 10G SFP+ DP EP102Fi4A Adapter
1bd4 0032 10G SFP+ DP EP102Fi4 Adapter
@@ -22570,8 +22596,15 @@
1520 I350 Ethernet Controller Virtual Function
1521 I350 Gigabit Network Connection
1028 0602 Gigabit 2P I350-t LOM
+ 1028 0693 Gigabit 2P I350-t LOM
+ 1028 06e2 Gigabit 2P I350-t LOM
+ 1028 0757 Gigabit I350-t LOM
+ 1028 075a Gigabit I350-t LOM
1028 1f60 Gigabit 4P I350-t rNDC
1028 1f62 Gigabit 4P X540/I350 rNDC
+ 1028 1fa8 Ethernet 10G 4P X550/I350 rNDC
+ 1028 1fa9 Ethernet 10G 4P X550 rNDC
+ 1028 1faa Gigabit 4P X550/I350 rNDC
1028 ff9a Gigabit 4P X710/I350 rNDC
103c 17d1 Ethernet 1Gb 4-port 366FLR Adapter
103c 2003 Ethernet 1Gb 2-port 367i Adapter
@@ -22590,6 +22623,7 @@
15d9 0652 Dual Port i350 GbE MicroLP [AOC-CGP-i2]
17aa 1074 ThinkServer I350-T4 AnyFabric
17aa 4005 I350 Gigabit Network Connection
+ 18d4 0c07 I350 1Gb 2-port RJ45 OCP Mezz Card MOP41-I-1GT2
1bd4 001d 1G base-T QP EP014Ti1 Adapter
1bd4 0035 1G base-T QP EP014Ti1 Adapter
8086 0001 Ethernet Server Adapter I350-T4
@@ -22698,6 +22732,7 @@
1028 1fa9 Ethernet 10G 4P X550 rNDC
1590 00d1 Ethernet 10Gb 2-port 562T Adapter
1590 00d2 Ethernet 10Gb 2-port 562FLR-T Adapter
+ 18d4 0c08 X550 10Gb 2-port RJ45 OCP Mezz Card MOP81-I-10GT2
8086 0001 Ethernet Converged Network Adapter X550-T2
8086 001a Ethernet Converged Network Adapter X550-T2
8086 0022 Ethernet Converged Network Adapter X550-T2
@@ -22782,11 +22817,11 @@
108e 0000 Ethernet Controller X710 for 10GBASE-T
108e 4857 Ethernet Controller X710 for 10GBASE-T
1587 Ethernet Controller XL710 for 20GbE backplane
- 103c 0000 HP Flex-20 20Gb 2-port 660FLB Adapter
- 103c 22fe HP Flex-20 20Gb 2-port 660FLB Adapter
+ 103c 0000 HPE Ethernet 10/20Gb 2-port 660FLB Adapter
+ 103c 22fe HPE Ethernet 10/20Gb 2-port 660FLB Adapter
1588 Ethernet Controller XL710 for 20GbE backplane
- 103c 0000 HP Flex-20 20Gb 2-port 660M Adapter
- 103c 22ff HP Flex-20 20Gb 2-port 660M Adapter
+ 103c 0000 HPE Ethernet 10/20Gb 2-port 660M Adapter
+ 103c 22ff HPE Ethernet 10/20Gb 2-port 660M Adapter
1589 Ethernet Controller X710/X557-AT 10GBASE-T
108e 0000 Quad Port 10GBase-T Adapter
108e 7b1c Quad Port 10GBase-T Adapter
@@ -23169,7 +23204,7 @@
1e09 7 Series Chipset Family 2-port SATA Controller [IDE mode]
144d c652 NP300E5C series laptop
1e0e 7 Series/C210 Series Chipset Family SATA Controller [RAID mode]
- 1e10 7 Series/C210 Series Chipset Family PCI Express Root Port 1
+ 1e10 7 Series/C216 Chipset Family PCI Express Root Port 1
1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
@@ -23181,7 +23216,7 @@
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1e14 7 Series/C210 Series Chipset Family PCI Express Root Port 3
- 1e16 7 Series/C210 Series Chipset Family PCI Express Root Port 4
+ 1e16 7 Series/C216 Chipset Family PCI Express Root Port 4
1043 108d VivoBook X202EV
1043 1477 N56VZ
144d c652 NP300E5C series laptop
@@ -23194,7 +23229,7 @@
1e1c 7 Series/C210 Series Chipset Family PCI Express Root Port 7
1e1e 7 Series/C210 Series Chipset Family PCI Express Root Port 8
1849 1e1e Motherboard
- 1e20 7 Series/C210 Series Chipset Family High Definition Audio Controller
+ 1e20 7 Series/C216 Chipset Family High Definition Audio Controller
1028 054b Dell XPS One 2710
1043 108d VivoBook X202EV
1043 1477 N56VZ
@@ -23203,7 +23238,7 @@
1043 8445 ASUS P8Z77-V LX Motherboard
144d c652 NP300E5C series laptop
1849 1898 Z77 Extreme4 motherboard
- 1e22 7 Series/C210 Series Chipset Family SMBus Controller
+ 1e22 7 Series/C216 Chipset Family SMBus Controller
1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
@@ -23213,14 +23248,14 @@
1e24 7 Series/C210 Series Chipset Family Thermal Management Controller
1043 1517 Zenbook Prime UX31A
1e25 7 Series/C210 Series Chipset Family DMI to PCI Bridge
- 1e26 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1
+ 1e26 7 Series/C216 Chipset Family USB Enhanced Host Controller #1
1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1043 84ca P8 series motherboard
144d c652 NP300E5C series laptop
1849 1e26 Motherboard
- 1e2d 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2
+ 1e2d 7 Series/C216 Chipset Family USB Enhanced Host Controller #2
1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
@@ -23235,7 +23270,7 @@
1043 84ca P8 series motherboard
1849 1e31 Motherboard
1e33 7 Series/C210 Series Chipset Family LAN Controller
- 1e3a 7 Series/C210 Series Chipset Family MEI Controller #1
+ 1e3a 7 Series/C216 Chipset Family MEI Controller #1
1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
@@ -26234,10 +26269,21 @@
37cd X722 Virtual Function
37ce Ethernet Connection X722 for 10GbE backplane
1590 0215 Ethernet 10Gb 2-port 568i Adapter
+ 17aa 4023 Intel Ethernet Connection X722 for 10GbE backplane
37cf Ethernet Connection X722 for 10GbE QSFP+
37d0 Ethernet Connection X722 for 10GbE SFP+
37d1 Ethernet Connection X722 for 1GbE
+ 17aa 4020 Intel Ethernet Connection X722 for 1GbE
+ 17aa 4021 Intel Ethernet Connection X722 for 1GbE
+ 17aa 4022 Intel Ethernet Connection X722 for 1GbE
+ 8086 4020 Ethernet Connection X722 for 1GbE
+ 8086 4021 Ethernet Connection X722 for 1GbE
+ 8086 4022 Ethernet Connection X722 for 1GbE
37d2 Ethernet Connection X722 for 10GBASE-T
+ 17aa 4020 Intel Ethernet Connection X722 for 10GBASE
+ 17aa 4021 Intel Ethernet Connection X722 for 10GBASE
+ 8086 4020 Ethernet Connection X722 for 10GBASE
+ 8086 4021 Ethernet Connection X722 for 10GBASE
37d3 Ethernet Connection X722 for 10GbE SFP+
37d4 Ethernet Connection X722 for 10GbE QSFP+
37d9 X722 Hyper-V Virtual Function
diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c
index 305d0bf..63c0f20 100644
--- a/sys/amd64/amd64/initcpu.c
+++ b/sys/amd64/amd64/initcpu.c
@@ -108,6 +108,20 @@ init_amd(void)
wrmsr(0xc001102a, msr);
}
}
+
+ /*
+ * Work around Erratum 793: Specific Combination of Writes to Write
+ * Combined Memory Types and Locked Instructions May Cause Core Hang.
+ * See Revision Guide for AMD Family 16h Models 00h-0Fh Processors,
+ * revision 3.04 or later, publication 51810.
+ */
+ if (CPUID_TO_FAMILY(cpu_id) == 0x16 && CPUID_TO_MODEL(cpu_id) <= 0xf) {
+ if ((cpu_feature2 & CPUID2_HV) == 0) {
+ msr = rdmsr(0xc0011020);
+ msr |= (uint64_t)1 << 15;
+ wrmsr(0xc0011020, msr);
+ }
+ }
}
/*
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index f7d93de..ce07e0f 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -409,6 +409,7 @@ void
invltlb_invpcid_handler(void)
{
struct invpcid_descr d;
+ uint32_t generation;
#ifdef COUNT_XINVLTLB_HITS
xhits_gbl[PCPU_GET(cpuid)]++;
@@ -417,17 +418,20 @@ invltlb_invpcid_handler(void)
(*ipi_invltlb_counts[PCPU_GET(cpuid)])++;
#endif /* COUNT_IPIS */
+ generation = smp_tlb_generation;
d.pcid = smp_tlb_pmap->pm_pcids[PCPU_GET(cpuid)].pm_pcid;
d.pad = 0;
d.addr = 0;
invpcid(&d, smp_tlb_pmap == kernel_pmap ? INVPCID_CTXGLOB :
INVPCID_CTX);
- atomic_add_int(&smp_tlb_wait, 1);
+ PCPU_SET(smp_tlb_done, generation);
}
void
invltlb_pcid_handler(void)
{
+ uint32_t generation;
+
#ifdef COUNT_XINVLTLB_HITS
xhits_gbl[PCPU_GET(cpuid)]++;
#endif /* COUNT_XINVLTLB_HITS */
@@ -435,6 +439,7 @@ invltlb_pcid_handler(void)
(*ipi_invltlb_counts[PCPU_GET(cpuid)])++;
#endif /* COUNT_IPIS */
+ generation = smp_tlb_generation; /* Overlap with serialization */
if (smp_tlb_pmap == kernel_pmap) {
invltlb_glob();
} else {
@@ -450,5 +455,5 @@ invltlb_pcid_handler(void)
smp_tlb_pmap->pm_pcids[PCPU_GET(cpuid)].pm_pcid);
}
}
- atomic_add_int(&smp_tlb_wait, 1);
+ PCPU_SET(smp_tlb_done, generation);
}
diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
index 4f85e1f..24009db 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -608,6 +608,8 @@ amd64_set_ldt(td, uap, descs)
largest_ld = uap->start + uap->num;
if (largest_ld > max_ldt_segment)
largest_ld = max_ldt_segment;
+ if (largest_ld < uap->start)
+ return (EINVAL);
i = largest_ld - uap->start;
mtx_lock(&dt_lock);
bzero(&((struct user_segment_descriptor *)(pldt->ldt_base))
@@ -620,7 +622,8 @@ amd64_set_ldt(td, uap, descs)
/* verify range of descriptors to modify */
largest_ld = uap->start + uap->num;
if (uap->start >= max_ldt_segment ||
- largest_ld > max_ldt_segment)
+ largest_ld > max_ldt_segment ||
+ largest_ld < uap->start)
return (EINVAL);
}
diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h
index 91e8fb2..a4f4e1d 100644
--- a/sys/amd64/include/pcpu.h
+++ b/sys/amd64/include/pcpu.h
@@ -65,7 +65,8 @@
u_int pc_vcpu_id; /* Xen vCPU ID */ \
uint32_t pc_pcid_next; \
uint32_t pc_pcid_gen; \
- char __pad[149] /* be divisor of PAGE_SIZE \
+ uint32_t pc_smp_tlb_done; /* TLB op acknowledgement */ \
+ char __pad[145] /* be divisor of PAGE_SIZE \
after cache alignment */
#define PC_DBREG_CMD_NONE 0
diff --git a/sys/arm/allwinner/axp209.c b/sys/arm/allwinner/axp209.c
index 2283fe3..2c00742 100644
--- a/sys/arm/allwinner/axp209.c
+++ b/sys/arm/allwinner/axp209.c
@@ -50,14 +50,92 @@ __FBSDID("$FreeBSD$");
#include <dev/gpio/gpiobusvar.h>
-#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/extres/regulator/regulator.h>
+
#include <arm/allwinner/axp209reg.h>
#include "iicbus_if.h"
#include "gpio_if.h"
+#include "regdev_if.h"
+
+MALLOC_DEFINE(M_AXP209_REG, "Axp209 regulator", "Axp209 power regulator");
+
+struct axp209_regdef {
+ intptr_t id;
+ char *name;
+ uint8_t enable_reg;
+ uint8_t enable_mask;
+ uint8_t voltage_reg;
+ uint8_t voltage_mask;
+ uint8_t voltage_shift;
+ int voltage_min;
+ int voltage_max;
+ int voltage_step;
+ int voltage_nstep;
+};
+
+static struct axp209_regdef axp209_regdefs[] = {
+ {
+ .id = AXP209_REG_ID_DCDC2,
+ .name = "dcdc2",
+ .enable_reg = AXP209_POWERCTL,
+ .enable_mask = AXP209_POWERCTL_DCDC2,
+ .voltage_reg = AXP209_REG_DCDC2_VOLTAGE,
+ .voltage_mask = 0x3f,
+ .voltage_min = 700,
+ .voltage_max = 2275,
+ .voltage_step = 25,
+ .voltage_nstep = 64,
+ },
+ {
+ .id = AXP209_REG_ID_DCDC3,
+ .name = "dcdc3",
+ .enable_reg = AXP209_POWERCTL,
+ .enable_mask = AXP209_POWERCTL_DCDC3,
+ .voltage_reg = AXP209_REG_DCDC3_VOLTAGE,
+ .voltage_mask = 0x7f,
+ .voltage_min = 700,
+ .voltage_max = 3500,
+ .voltage_step = 25,
+ .voltage_nstep = 128,
+ },
+ {
+ .id = AXP209_REG_ID_LDO2,
+ .name = "ldo2",
+ .enable_reg = AXP209_POWERCTL,
+ .enable_mask = AXP209_POWERCTL_LDO2,
+ .voltage_reg = AXP209_REG_LDO24_VOLTAGE,
+ .voltage_mask = 0xf0,
+ .voltage_shift = 4,
+ .voltage_min = 1800,
+ .voltage_max = 3300,
+ .voltage_step = 100,
+ .voltage_nstep = 16,
+ },
+ {
+ .id = AXP209_REG_ID_LDO3,
+ .name = "ldo3",
+ .enable_reg = AXP209_POWERCTL,
+ .enable_mask = AXP209_POWERCTL_LDO3,
+ .voltage_reg = AXP209_REG_LDO3_VOLTAGE,
+ .voltage_mask = 0x7f,
+ .voltage_min = 700,
+ .voltage_max = 2275,
+ .voltage_step = 25,
+ .voltage_nstep = 128,
+ },
+};
+
+struct axp209_reg_sc {
+ struct regnode *regnode;
+ device_t base_dev;
+ struct axp209_regdef *def;
+ phandle_t xref;
+ struct regnode_std_param *param;
+};
struct axp209_softc {
device_t dev;
@@ -67,6 +145,10 @@ struct axp209_softc {
struct intr_config_hook intr_hook;
device_t gpiodev;
struct mtx mtx;
+
+ /* Regulators */
+ struct axp209_reg_sc **regs;
+ int nregs;
};
/* GPIO3 is different, don't expose it for now */
@@ -125,6 +207,115 @@ axp209_write(device_t dev, uint8_t reg, uint8_t data)
}
static int
+axp209_regnode_init(struct regnode *regnode)
+{
+ return (0);
+}
+
+static int
+axp209_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
+{
+ struct axp209_reg_sc *sc;
+ uint8_t val;
+
+ sc = regnode_get_softc(regnode);
+
+ axp209_read(sc->base_dev, sc->def->enable_reg, &val, 1);
+ if (enable)
+ val |= sc->def->enable_mask;
+ else
+ val &= ~sc->def->enable_mask;
+ axp209_write(sc->base_dev, sc->def->enable_reg, val);
+
+ *udelay = 0;
+
+ return (0);
+}
+
+static void
+axp209_regnode_reg_to_voltage(struct axp209_reg_sc *sc, uint8_t val, int *uv)
+{
+ if (val < sc->def->voltage_nstep)
+ *uv = sc->def->voltage_min + val * sc->def->voltage_step;
+ else
+ *uv = sc->def->voltage_min +
+ (sc->def->voltage_nstep * sc->def->voltage_step);
+ *uv *= 1000;
+}
+
+static int
+axp209_regnode_voltage_to_reg(struct axp209_reg_sc *sc, int min_uvolt,
+ int max_uvolt, uint8_t *val)
+{
+ uint8_t nval;
+ int nstep, uvolt;
+
+ nval = 0;
+ uvolt = sc->def->voltage_min * 1000;
+
+ for (nstep = 0; nstep < sc->def->voltage_nstep && uvolt < min_uvolt;
+ nstep++) {
+ ++nval;
+ uvolt += (sc->def->voltage_step * 1000);
+ }
+ if (uvolt > max_uvolt)
+ return (EINVAL);
+
+ *val = nval;
+ return (0);
+}
+
+static int
+axp209_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
+ int max_uvolt, int *udelay)
+{
+ struct axp209_reg_sc *sc;
+ uint8_t val;
+
+ sc = regnode_get_softc(regnode);
+
+ if (!sc->def->voltage_step)
+ return (ENXIO);
+
+ if (axp209_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
+ return (ERANGE);
+
+ axp209_write(sc->base_dev, sc->def->voltage_reg, val);
+
+ *udelay = 0;
+
+ return (0);
+}
+
+static int
+axp209_regnode_get_voltage(struct regnode *regnode, int *uvolt)
+{
+ struct axp209_reg_sc *sc;
+ uint8_t val;
+
+ sc = regnode_get_softc(regnode);
+
+ if (!sc->def->voltage_step)
+ return (ENXIO);
+
+ axp209_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
+ axp209_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
+
+ return (0);
+}
+
+static regnode_method_t axp209_regnode_methods[] = {
+ /* Regulator interface */
+ REGNODEMETHOD(regnode_init, axp209_regnode_init),
+ REGNODEMETHOD(regnode_enable, axp209_regnode_enable),
+ REGNODEMETHOD(regnode_set_voltage, axp209_regnode_set_voltage),
+ REGNODEMETHOD(regnode_get_voltage, axp209_regnode_get_voltage),
+ REGNODEMETHOD_END
+};
+DEFINE_CLASS_1(axp209_regnode, axp209_regnode_class, axp209_regnode_methods,
+ sizeof(struct axp209_reg_sc), regnode_class);
+
+static int
axp209_sysctl(SYSCTL_HANDLER_ARGS)
{
device_t dev = arg1;
@@ -517,6 +708,63 @@ axp209_get_node(device_t dev, device_t bus)
return (ofw_bus_get_node(dev));
}
+static struct axp209_reg_sc *
+axp209_reg_attach(device_t dev, phandle_t node,
+ struct axp209_regdef *def)
+{
+ struct axp209_reg_sc *reg_sc;
+ struct regnode_init_def initdef;
+ struct regnode *regnode;
+
+ memset(&initdef, 0, sizeof(initdef));
+ if (regulator_parse_ofw_stdparam(dev, node, &initdef) != 0) {
+ device_printf(dev, "cannot create regulator\n");
+ return (NULL);
+ }
+ if (initdef.std_param.min_uvolt == 0)
+ initdef.std_param.min_uvolt = def->voltage_min * 1000;
+ if (initdef.std_param.max_uvolt == 0)
+ initdef.std_param.max_uvolt = def->voltage_max * 1000;
+ initdef.id = def->id;
+ initdef.ofw_node = node;
+ regnode = regnode_create(dev, &axp209_regnode_class, &initdef);
+ if (regnode == NULL) {
+ device_printf(dev, "cannot create regulator\n");
+ return (NULL);
+ }
+
+ reg_sc = regnode_get_softc(regnode);
+ reg_sc->regnode = regnode;
+ reg_sc->base_dev = dev;
+ reg_sc->def = def;
+ reg_sc->xref = OF_xref_from_node(node);
+ reg_sc->param = regnode_get_stdparam(regnode);
+
+ regnode_register(regnode);
+
+ return (reg_sc);
+}
+
+static int
+axp209_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
+ intptr_t *num)
+{
+ struct axp209_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->nregs; i++) {
+ if (sc->regs[i] == NULL)
+ continue;
+ if (sc->regs[i]->xref == xref) {
+ *num = sc->regs[i]->def->id;
+ return (0);
+ }
+ }
+
+ return (ENXIO);
+}
+
static void
axp209_start(void *pdev)
{
@@ -654,6 +902,9 @@ static int
axp209_attach(device_t dev)
{
struct axp209_softc *sc;
+ struct axp209_reg_sc *reg;
+ phandle_t rnode, child;
+ int i;
sc = device_get_softc(dev);
mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
@@ -669,6 +920,29 @@ axp209_attach(device_t dev)
if (config_intrhook_establish(&sc->intr_hook) != 0)
return (ENOMEM);
+ sc->nregs = nitems(axp209_regdefs);
+ sc->regs = malloc(sizeof(struct axp209_reg_sc *) * sc->nregs,
+ M_AXP209_REG, M_WAITOK | M_ZERO);
+
+ /* Attach known regulators that exist in the DT */
+ rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators");
+ if (rnode > 0) {
+ for (i = 0; i < sc->nregs; i++) {
+ child = ofw_bus_find_child(rnode,
+ axp209_regdefs[i].name);
+ if (child == 0)
+ continue;
+ reg = axp209_reg_attach(dev, child, &axp209_regdefs[i]);
+ if (reg == NULL) {
+ device_printf(dev,
+ "cannot attach regulator %s\n",
+ axp209_regdefs[i].name);
+ continue;
+ }
+ sc->regs[i] = reg;
+ }
+ }
+
sc->gpiodev = gpiobus_attach_bus(dev);
return (0);
@@ -690,6 +964,9 @@ static device_method_t axp209_methods[] = {
DEVMETHOD(gpio_pin_toggle, axp209_gpio_pin_toggle),
DEVMETHOD(gpio_map_gpios, axp209_gpio_map_gpios),
+ /* Regdev interface */
+ DEVMETHOD(regdev_map, axp209_regdev_map),
+
/* OFW bus interface */
DEVMETHOD(ofw_bus_get_node, axp209_get_node),
diff --git a/sys/arm/allwinner/axp209reg.h b/sys/arm/allwinner/axp209reg.h
index 941a72b..38e5401 100644
--- a/sys/arm/allwinner/axp209reg.h
+++ b/sys/arm/allwinner/axp209reg.h
@@ -146,6 +146,19 @@
#define AXP209_GPIO_DATA(x) (1 << (x + 4))
+/* Regulators registers */
+#define AXP209_POWERCTL 0x12
+#define AXP209_POWERCTL_DCDC3 (1 << 1)
+#define AXP209_POWERCTL_LDO2 (1 << 2)
+#define AXP209_POWERCTL_LDO4 (1 << 3)
+#define AXP209_POWERCTL_DCDC2 (1 << 4)
+#define AXP209_POWERCTL_LDO3 (1 << 6)
+
+#define AXP209_REG_DCDC2_VOLTAGE 0x23
+#define AXP209_REG_DCDC3_VOLTAGE 0x27
+#define AXP209_REG_LDO24_VOLTAGE 0x28
+#define AXP209_REG_LDO3_VOLTAGE 0x29
+
enum axp209_sensor {
AXP209_TEMP,
AXP209_ACVOLT,
@@ -157,4 +170,15 @@ enum axp209_sensor {
AXP209_BATDISCHARGECURRENT,
};
+enum axp209_regulators {
+ AXP209_REG_ID_DCDC2,
+ AXP209_REG_ID_DCDC3,
+ AXP209_REG_ID_LDO1,
+ AXP209_REG_ID_LDO2,
+ AXP209_REG_ID_LDO3,
+ /* LDO4 is weird, need to find a correct way to handle it */
+ /* AXP209_REG_ID_LDO4, */
+ AXP209_REG_ID_LDO5,
+};
+
#endif /* _AXP209REG_H_ */
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c b/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c
new file mode 100644
index 0000000..86432cf
--- /dev/null
+++ b/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c
@@ -0,0 +1,335 @@
+/*-
+ * Copyright (C) 2016 Oleksandr Tymoshenko <gonzo@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.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/selinfo.h>
+#include <sys/poll.h>
+#include <sys/uio.h>
+#include <sys/conf.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_mbox.h>
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
+#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
+
+#include "mbox_if.h"
+
+#ifdef DEBUG
+#define DPRINTF(fmt, ...) do { \
+ printf("%s:%u: ", __func__, __LINE__); \
+ printf(fmt, ##__VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+#define FT5406_LOCK(_sc) \
+ mtx_lock(&(_sc)->sc_mtx)
+#define FT5406_UNLOCK(_sc) \
+ mtx_unlock(&(_sc)->sc_mtx)
+#define FT5406_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
+ "ft5406", MTX_DEF)
+#define FT5406_LOCK_DESTROY(_sc) \
+ mtx_destroy(&_sc->sc_mtx);
+#define FT5406_LOCK_ASSERT(_sc) \
+ mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
+
+#define FT5406_DEVICE_MODE 0
+#define FT5406_GESTURE_ID 1
+#define FT5406_NUM_POINTS 2
+#define FT5406_POINT_XH(n) (0 + 3 + (n)*6)
+#define FT5406_POINT_XL(n) (1 + 3 + (n)*6)
+#define FT5406_POINT_YH(n) (2 + 3 + (n)*6)
+#define FT5406_POINT_YL(n) (3 + 3 + (n)*6)
+#define FT5406_WINDOW_SIZE 64
+
+#define GET_NUM_POINTS(buf) (buf[FT5406_NUM_POINTS])
+#define GET_X(buf, n) (((buf[FT5406_POINT_XH(n)] & 0xf) << 8) | \
+ (buf[FT5406_POINT_XL(n)]))
+#define GET_Y(buf, n) (((buf[FT5406_POINT_YH(n)] & 0xf) << 8) | \
+ (buf[FT5406_POINT_YL(n)]))
+#define GET_TOUCH_ID(buf, n) ((buf[FT5406_POINT_YH(n)] >> 4) & 0xf)
+
+#define NO_POINTS 99
+#define SCREEN_WIDTH 800
+#define SCREEN_HEIGHT 480
+#define SCREEN_WIDTH_MM 155
+#define SCREEN_HEIGHT_MM 86
+#define SCREEN_RES_X (SCREEN_WIDTH / SCREEN_WIDTH_MM)
+#define SCREEN_RES_Y (SCREEN_HEIGHT / SCREEN_HEIGHT_MM)
+#define MAX_TOUCH_ID (10 - 1)
+
+struct ft5406ts_softc {
+ device_t sc_dev;
+ struct mtx sc_mtx;
+ int sc_tick;
+ struct callout sc_callout;
+
+ /* mbox buffer (mapped to KVA) */
+ uint8_t *touch_buf;
+
+ /* initial hook for waiting mbox intr */
+ struct intr_config_hook sc_init_hook;
+
+ struct evdev_dev *sc_evdev;
+
+ uint8_t sc_window[FT5406_WINDOW_SIZE];
+};
+
+static evdev_open_t ft5406ts_ev_open;
+static evdev_close_t ft5406ts_ev_close;
+
+static const struct evdev_methods ft5406ts_evdev_methods = {
+ .ev_open = &ft5406ts_ev_open,
+ .ev_close = &ft5406ts_ev_close,
+};
+
+static void
+ft5406ts_callout(void *data)
+{
+ struct ft5406ts_softc *sc = (struct ft5406ts_softc *)data;
+ int points;
+ int id, i, x, y;
+
+ FT5406_LOCK_ASSERT(sc);
+
+ memcpy(sc->sc_window, sc->touch_buf, FT5406_WINDOW_SIZE);
+ sc->touch_buf[FT5406_NUM_POINTS] = NO_POINTS;
+
+ points = GET_NUM_POINTS(sc->sc_window);
+ /*
+ * No update from VC - do nothing.
+ */
+ if (points == NO_POINTS)
+ goto out;
+
+ for (i = 0; i < points; i++) {
+ id = GET_TOUCH_ID(sc->sc_window, i);
+ x = GET_X(sc->sc_window, i);
+ y = GET_Y(sc->sc_window, i);
+
+ if (id > MAX_TOUCH_ID) {
+ device_printf(sc->sc_dev, "bad touch id: %d", id);
+ continue;
+ }
+ evdev_push_event(sc->sc_evdev, EV_ABS, ABS_MT_SLOT, id);
+ evdev_push_event(sc->sc_evdev, EV_ABS, ABS_MT_TRACKING_ID, id);
+ evdev_push_event(sc->sc_evdev, EV_ABS, ABS_MT_POSITION_X, x);
+ evdev_push_event(sc->sc_evdev, EV_ABS, ABS_MT_POSITION_Y, y);
+ }
+ evdev_sync(sc->sc_evdev);
+out:
+ callout_reset(&sc->sc_callout, sc->sc_tick, ft5406ts_callout, sc);
+}
+
+static void
+ft5406ts_ev_close(struct evdev_dev *evdev, void *data)
+{
+ struct ft5406ts_softc *sc = (struct ft5406ts_softc *)data;
+
+ FT5406_LOCK_ASSERT(sc);
+
+ callout_stop(&sc->sc_callout);
+}
+
+static int
+ft5406ts_ev_open(struct evdev_dev *evdev, void *data)
+{
+ struct ft5406ts_softc *sc = (struct ft5406ts_softc *)data;
+
+ FT5406_LOCK_ASSERT(sc);
+
+ callout_reset(&sc->sc_callout, sc->sc_tick, ft5406ts_callout, sc);
+
+ return (0);
+}
+
+static void
+ft5406ts_init(void *arg)
+{
+ struct ft5406ts_softc *sc = arg;
+ struct bcm2835_mbox_tag_touchbuf msg;
+ uint32_t touchbuf;
+ int err;
+
+ /* release this hook (continue boot) */
+ config_intrhook_disestablish(&sc->sc_init_hook);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_TOUCHBUF;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body);
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->sc_dev, "failed to get touchbuf address\n");
+ return;
+ }
+
+ if (msg.body.resp.address == 0) {
+ device_printf(sc->sc_dev, "touchscreen not detected\n");
+ return;
+ }
+
+ touchbuf = VCBUS_TO_PHYS(msg.body.resp.address);
+ sc->touch_buf = (uint8_t*)pmap_mapdev(touchbuf, FT5406_WINDOW_SIZE);
+
+ /* 60Hz */
+ sc->sc_tick = hz * 17 / 1000;
+ if (sc->sc_tick == 0)
+ sc->sc_tick = 1;
+
+ sc->sc_evdev = evdev_alloc();
+ evdev_set_name(sc->sc_evdev, device_get_desc(sc->sc_dev));
+ evdev_set_phys(sc->sc_evdev, device_get_nameunit(sc->sc_dev));
+ evdev_set_id(sc->sc_evdev, BUS_HOST, 0, 0, 0);
+ evdev_set_methods(sc->sc_evdev, sc, &ft5406ts_evdev_methods);
+ evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
+ evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
+ evdev_support_prop(sc->sc_evdev, INPUT_PROP_DIRECT);
+ evdev_support_event(sc->sc_evdev, EV_SYN);
+ evdev_support_event(sc->sc_evdev, EV_ABS);
+
+ evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT, 0, 0,
+ MAX_TOUCH_ID, 0, 0, 0);
+ evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID, 0, -1,
+ MAX_TOUCH_ID, 0, 0, 0);
+ evdev_support_abs(sc->sc_evdev, ABS_MT_POSITION_X, 0, 0,
+ SCREEN_WIDTH, 0, 0, SCREEN_RES_X);
+ evdev_support_abs(sc->sc_evdev, ABS_MT_POSITION_Y, 0, 0,
+ SCREEN_HEIGHT, 0, 0, SCREEN_RES_Y);
+
+ err = evdev_register_mtx(sc->sc_evdev, &sc->sc_mtx);
+ if (err) {
+ evdev_free(sc->sc_evdev);
+ sc->sc_evdev = NULL; /* Avoid double free */
+ return;
+ }
+
+ sc->touch_buf[FT5406_NUM_POINTS] = NO_POINTS;
+ callout_init_mtx(&sc->sc_callout, &sc->sc_mtx, 0);
+}
+
+static int
+ft5406ts_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "rpi,rpi-ft5406"))
+ return (ENXIO);
+
+ device_set_desc(dev, "FT5406 touchscreen (VC memory interface)");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ft5406ts_attach(device_t dev)
+{
+ struct ft5406ts_softc *sc;
+
+ /* set self dev */
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ /* register callback for using mbox when interrupts are enabled */
+ sc->sc_init_hook.ich_func = ft5406ts_init;
+ sc->sc_init_hook.ich_arg = sc;
+
+ FT5406_LOCK_INIT(sc);
+
+ if (config_intrhook_establish(&sc->sc_init_hook) != 0) {
+ device_printf(dev, "config_intrhook_establish failed\n");
+ FT5406_LOCK_DESTROY(sc);
+ return (ENOMEM);
+ }
+
+ return (0);
+}
+
+static int
+ft5406ts_detach(device_t dev)
+{
+ struct ft5406ts_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ evdev_free(sc->sc_evdev);
+
+ FT5406_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static device_method_t ft5406ts_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ft5406ts_probe),
+ DEVMETHOD(device_attach, ft5406ts_attach),
+ DEVMETHOD(device_detach, ft5406ts_detach),
+
+ DEVMETHOD_END
+};
+
+static devclass_t ft5406ts_devclass;
+static driver_t ft5406ts_driver = {
+ "ft5406ts",
+ ft5406ts_methods,
+ sizeof(struct ft5406ts_softc),
+};
+
+DRIVER_MODULE(ft5406ts, ofwbus, ft5406ts_driver, ft5406ts_devclass, 0, 0);
+MODULE_DEPEND(ft5406ts, evdev, 1, 1, 1);
diff --git a/sys/arm/broadcom/bcm2835/files.bcm283x b/sys/arm/broadcom/bcm2835/files.bcm283x
index 27c2f6d..d9ddb75 100644
--- a/sys/arm/broadcom/bcm2835/files.bcm283x
+++ b/sys/arm/broadcom/bcm2835/files.bcm283x
@@ -6,6 +6,7 @@ arm/broadcom/bcm2835/bcm2835_cpufreq.c standard
arm/broadcom/bcm2835/bcm2835_dma.c standard
arm/broadcom/bcm2835/bcm2835_fb.c optional sc
arm/broadcom/bcm2835/bcm2835_fbd.c optional vt
+arm/broadcom/bcm2835/bcm2835_ft5406.c optional evdev bcm2835_ft5406
arm/broadcom/bcm2835/bcm2835_gpio.c optional gpio
arm/broadcom/bcm2835/bcm2835_intr.c standard
arm/broadcom/bcm2835/bcm2835_machdep.c standard
diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE
index 312659b..be6a98f 100644
--- a/sys/arm/conf/BEAGLEBONE
+++ b/sys/arm/conf/BEAGLEBONE
@@ -133,3 +133,6 @@ device hdmi
device ums
device ukbd
device kbdmux
+
+# Uncomment to enable evdev support for ti_adc
+# options EVDEV_SUPPORT
diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B
index 58d05ca..5e8aee2 100644
--- a/sys/arm/conf/RPI-B
+++ b/sys/arm/conf/RPI-B
@@ -94,4 +94,4 @@ options FDT # Configure using FDT/DTB data
# handed to kernel via U-Boot and ubldr.
#options FDT_DTB_STATIC
#makeoptions FDT_DTS_FILE=rpi.dts
-makeoptions MODULES_EXTRA=dtb/rpi
+makeoptions MODULES_EXTRA="dtb/rpi rpi_ft5406"
diff --git a/sys/arm/conf/RPI2 b/sys/arm/conf/RPI2
index 75e1b7e..82293ad 100644
--- a/sys/arm/conf/RPI2
+++ b/sys/arm/conf/RPI2
@@ -98,4 +98,4 @@ options FDT # Configure using FDT/DTB data
# handed to kernel via U-Boot and ubldr.
#options FDT_DTB_STATIC
#makeoptions FDT_DTS_FILE=rpi2.dts
-makeoptions MODULES_EXTRA=dtb/rpi
+makeoptions MODULES_EXTRA="dtb/rpi rpi_ft5406"
diff --git a/sys/arm/ti/ti_adc.c b/sys/arm/ti/ti_adc.c
index 9f545e0..154cd78 100644
--- a/sys/arm/ti/ti_adc.c
+++ b/sys/arm/ti/ti_adc.c
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_evdev.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -52,6 +54,11 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#ifdef EVDEV_SUPPORT
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+#endif
+
#include <arm/ti/ti_prcm.h>
#include <arm/ti/ti_adcreg.h>
#include <arm/ti/ti_adcvar.h>
@@ -80,6 +87,20 @@ static struct ti_adc_input ti_adc_inputs[TI_ADC_NPINS] = {
static int ti_adc_samples[5] = { 0, 2, 4, 8, 16 };
+static int ti_adc_detach(device_t dev);
+
+#ifdef EVDEV_SUPPORT
+static void
+ti_adc_ev_report(struct ti_adc_softc *sc)
+{
+
+ evdev_push_event(sc->sc_evdev, EV_ABS, ABS_X, sc->sc_x);
+ evdev_push_event(sc->sc_evdev, EV_ABS, ABS_Y, sc->sc_y);
+ evdev_push_event(sc->sc_evdev, EV_KEY, BTN_TOUCH, sc->sc_pen_down);
+ evdev_sync(sc->sc_evdev);
+}
+#endif /* EVDEV */
+
static void
ti_adc_enable(struct ti_adc_softc *sc)
{
@@ -450,7 +471,14 @@ ti_adc_tsc_read_data(struct ti_adc_softc *sc)
#ifdef DEBUG_TSC
device_printf(sc->sc_dev, "touchscreen x: %d, y: %d\n", x, y);
#endif
- /* TODO: That's where actual event reporting should take place */
+
+#ifdef EVDEV_SUPPORT
+ if ((sc->sc_x != x) || (sc->sc_y != y)) {
+ sc->sc_x = x;
+ sc->sc_y = y;
+ ti_adc_ev_report(sc);
+ }
+#endif
}
static void
@@ -488,11 +516,17 @@ ti_adc_intr(void *arg)
status |= ADC_IRQ_HW_PEN_ASYNC;
ADC_WRITE4(sc, ADC_IRQENABLE_CLR,
ADC_IRQ_HW_PEN_ASYNC);
+#ifdef EVDEV_SUPPORT
+ ti_adc_ev_report(sc);
+#endif
}
if (rawstatus & ADC_IRQ_PEN_UP) {
sc->sc_pen_down = 0;
status |= ADC_IRQ_PEN_UP;
+#ifdef EVDEV_SUPPORT
+ ti_adc_ev_report(sc);
+#endif
}
if (status & ADC_IRQ_FIFO0_THRES)
@@ -840,6 +874,38 @@ ti_adc_attach(device_t dev)
ti_adc_setup(sc);
TI_ADC_UNLOCK(sc);
+#ifdef EVDEV_SUPPORT
+ if (sc->sc_tsc_wires > 0) {
+ sc->sc_evdev = evdev_alloc();
+ evdev_set_name(sc->sc_evdev, device_get_desc(dev));
+ evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
+ evdev_set_id(sc->sc_evdev, BUS_VIRTUAL, 0, 0, 0);
+ evdev_support_prop(sc->sc_evdev, INPUT_PROP_DIRECT);
+ evdev_support_event(sc->sc_evdev, EV_SYN);
+ evdev_support_event(sc->sc_evdev, EV_ABS);
+ evdev_support_event(sc->sc_evdev, EV_KEY);
+
+ evdev_support_abs(sc->sc_evdev, ABS_X, 0, 0,
+ ADC_MAX_VALUE, 0, 0, 0);
+ evdev_support_abs(sc->sc_evdev, ABS_Y, 0, 0,
+ ADC_MAX_VALUE, 0, 0, 0);
+
+ evdev_support_key(sc->sc_evdev, BTN_TOUCH);
+
+ err = evdev_register(sc->sc_evdev);
+ if (err) {
+ device_printf(dev,
+ "failed to register evdev: error=%d\n", err);
+ ti_adc_detach(dev);
+ return (err);
+ }
+
+ sc->sc_pen_down = 0;
+ sc->sc_x = -1;
+ sc->sc_y = -1;
+ }
+#endif /* EVDEV */
+
return (0);
}
@@ -854,6 +920,11 @@ ti_adc_detach(device_t dev)
TI_ADC_LOCK(sc);
ti_adc_reset(sc);
ti_adc_setup(sc);
+
+#ifdef EVDEV_SUPPORT
+ evdev_free(sc->sc_evdev);
+#endif
+
TI_ADC_UNLOCK(sc);
TI_ADC_LOCK_DESTROY(sc);
@@ -887,3 +958,6 @@ static devclass_t ti_adc_devclass;
DRIVER_MODULE(ti_adc, simplebus, ti_adc_driver, ti_adc_devclass, 0, 0);
MODULE_VERSION(ti_adc, 1);
MODULE_DEPEND(ti_adc, simplebus, 1, 1, 1);
+#ifdef EVDEV_SUPPORT
+MODULE_DEPEND(ti_adc, evdev, 1, 1, 1);
+#endif
diff --git a/sys/arm/ti/ti_adcreg.h b/sys/arm/ti/ti_adcreg.h
index ee15f16..bc3b972 100644
--- a/sys/arm/ti/ti_adcreg.h
+++ b/sys/arm/ti/ti_adcreg.h
@@ -122,5 +122,6 @@
#define ADC_FIFO_STEP_ID_MSK 0x000f0000
#define ADC_FIFO_STEP_ID_SHIFT 16
#define ADC_FIFO_DATA_MSK 0x00000fff
+#define ADC_MAX_VALUE 0xfff
#endif /* _TI_ADCREG_H_ */
diff --git a/sys/arm/ti/ti_adcvar.h b/sys/arm/ti/ti_adcvar.h
index 0cd0c34..b9cc0f0 100644
--- a/sys/arm/ti/ti_adcvar.h
+++ b/sys/arm/ti/ti_adcvar.h
@@ -55,6 +55,11 @@ struct ti_adc_softc {
int sc_yn_bit, sc_yn_inp;
uint32_t sc_tsc_enabled;
int sc_pen_down;
+#ifdef EVDEV_SUPPORT
+ int sc_x;
+ int sc_y;
+ struct evdev_dev *sc_evdev;
+#endif
};
struct ti_adc_input {
diff --git a/sys/boot/efi/Makefile b/sys/boot/efi/Makefile
index 21da86f..66481f8 100644
--- a/sys/boot/efi/Makefile
+++ b/sys/boot/efi/Makefile
@@ -4,7 +4,7 @@
# In-tree GCC does not support __attribute__((ms_abi)), but gcc newer
# than 4.5 supports it.
-.if ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 404500
+.if ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 40500
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
.if ${MK_FDT} != "no"
@@ -18,6 +18,6 @@ SUBDIR+= fdt
SUBDIR+= libefi loader boot1
.endif
-.endif # ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 404500
+.endif # ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 40500
.include <bsd.subdir.mk>
diff --git a/sys/boot/fdt/dts/arm/rpi.dts b/sys/boot/fdt/dts/arm/rpi.dts
index 548f888..23e1266 100644
--- a/sys/boot/fdt/dts/arm/rpi.dts
+++ b/sys/boot/fdt/dts/arm/rpi.dts
@@ -322,6 +322,11 @@
broadcom,depth = <0>; /* Set by VideoCore */
};
+ rpi_ft5406 {
+ compatible = "rpi,rpi-ft5406";
+ status = "okay";
+ };
+
leds {
compatible = "gpio-leds";
diff --git a/sys/boot/fdt/dts/arm/rpi2.dts b/sys/boot/fdt/dts/arm/rpi2.dts
index 951bca3..838800f 100644
--- a/sys/boot/fdt/dts/arm/rpi2.dts
+++ b/sys/boot/fdt/dts/arm/rpi2.dts
@@ -337,6 +337,11 @@
broadcom,depth = <0>; /* Set by VideoCore */
};
+ rpi_ft5406 {
+ compatible = "rpi,rpi-ft5406";
+ status = "okay";
+ };
+
leds {
compatible = "gpio-leds";
diff --git a/sys/boot/userboot/userboot/Makefile b/sys/boot/userboot/userboot/Makefile
index b64bcc0..ac3db42 100644
--- a/sys/boot/userboot/userboot/Makefile
+++ b/sys/boot/userboot/userboot/Makefile
@@ -49,9 +49,10 @@ BOOT_FORTH= yes
CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/i386
CFLAGS+= -DBF_DICTSIZE=15000
LIBFICL= ${.OBJDIR}/../ficl/libficl.a
-LIBSTAND= ${.OBJDIR}/../libstand/libstand.a
.endif
+LIBSTAND= ${.OBJDIR}/../libstand/libstand.a
+
.if ${MK_ZFS} != "no"
CFLAGS+= -DUSERBOOT_ZFS_SUPPORT
LIBZFSBOOT= ${.OBJDIR}/../zfs/libzfsboot.a
diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c
index 459a715..34aa704 100644
--- a/sys/cam/ata/ata_all.c
+++ b/sys/cam/ata/ata_all.c
@@ -88,6 +88,7 @@ ata_op_string(struct ata_cmd *cmd)
}
return "DSM";
case 0x08: return ("DEVICE_RESET");
+ case 0x0b: return ("REQUEST_SENSE_DATA_EXT");
case 0x20: return ("READ");
case 0x24: return ("READ48");
case 0x25: return ("READ_DMA48");
@@ -120,6 +121,12 @@ ata_op_string(struct ata_cmd *cmd)
case 0x47: return ("READ_LOG_DMA_EXT");
case 0x4a: return ("ZAC_MANAGEMENT_IN");
case 0x51: return ("CONFIGURE_STREAM");
+ case 0x57: return ("WRITE_LOG_DMA_EXT");
+ case 0x5b: return ("TRUSTED_NON_DATA");
+ case 0x5c: return ("TRUSTED_RECEIVE");
+ case 0x5d: return ("TRUSTED_RECEIVE_DMA");
+ case 0x5e: return ("TRUSTED_SEND");
+ case 0x5f: return ("TRUSTED_SEND_DMA");
case 0x60: return ("READ_FPDMA_QUEUED");
case 0x61: return ("WRITE_FPDMA_QUEUED");
case 0x63:
@@ -160,9 +167,12 @@ ata_op_string(struct ata_cmd *cmd)
}
return ("SEP_ATTN");
case 0x70: return ("SEEK");
+ case 0x77: return ("SET_DATE_TIME_EXT");
+ case 0x78: return ("ACCESSIBLE_MAX_ADDRESS_CONFIGURATION");
case 0x87: return ("CFA_TRANSLATE_SECTOR");
case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC");
case 0x92: return ("DOWNLOAD_MICROCODE");
+ case 0x93: return ("DOWNLOAD_MICROCODE_DMA");
case 0x9a: return ("ZAC_MANAGEMENT_OUT");
case 0xa0: return ("PACKET");
case 0xa1: return ("ATAPI_IDENTIFY");
@@ -180,6 +190,7 @@ ata_op_string(struct ata_cmd *cmd)
}
return ("SMART");
case 0xb1: return ("DEVICE CONFIGURATION");
+ case 0xb4: return ("SANITIZE_DEVICE");
case 0xc0: return ("CFA_ERASE");
case 0xc4: return ("READ_MUL");
case 0xc5: return ("WRITE_MUL");
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index b59c649..808dc72 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -926,8 +926,7 @@ adaclose(struct disk *dp)
if (error != 0)
xpt_print(periph->path, "Synchronize cache failed\n");
- else
- softc->flags &= ~ADA_FLAG_DIRTY;
+ softc->flags &= ~ADA_FLAG_DIRTY;
xpt_release_ccb(ccb);
cam_periph_unhold(periph);
}
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 83e2289..89c1304 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -9903,6 +9903,7 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
{
struct scsi_vpd_block_limits *bl_ptr;
struct ctl_lun *lun;
+ uint64_t ival;
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
@@ -9941,8 +9942,14 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
if (lun != NULL) {
scsi_ulto4b(lun->be_lun->opttxferlen, bl_ptr->opt_txfer_len);
if (lun->be_lun->flags & CTL_LUN_FLAG_UNMAP) {
- scsi_ulto4b(0xffffffff, bl_ptr->max_unmap_lba_cnt);
- scsi_ulto4b(0xffffffff, bl_ptr->max_unmap_blk_cnt);
+ ival = 0xffffffff;
+ ctl_get_opt_number(&lun->be_lun->options,
+ "unmap_max_lba", &ival);
+ scsi_ulto4b(ival, bl_ptr->max_unmap_lba_cnt);
+ ival = 0xffffffff;
+ ctl_get_opt_number(&lun->be_lun->options,
+ "unmap_max_descr", &ival);
+ scsi_ulto4b(ival, bl_ptr->max_unmap_blk_cnt);
if (lun->be_lun->ublockexp != 0) {
scsi_ulto4b((1 << lun->be_lun->ublockexp),
bl_ptr->opt_unmap_grain);
@@ -9956,8 +9963,10 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
scsi_ulto4b(0, bl_ptr->atomic_transfer_length_granularity);
scsi_ulto4b(0, bl_ptr->max_atomic_transfer_length_with_atomic_boundary);
scsi_ulto4b(0, bl_ptr->max_atomic_boundary_size);
+ ival = UINT64_MAX;
+ ctl_get_opt_number(&lun->be_lun->options, "write_same_max_lba", &ival);
+ scsi_u64to8b(ival, bl_ptr->max_write_same_length);
}
- scsi_u64to8b(UINT64_MAX, bl_ptr->max_write_same_length);
ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
@@ -10031,6 +10040,7 @@ ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len)
{
struct scsi_vpd_logical_block_prov *lbp_ptr;
struct ctl_lun *lun;
+ const char *value;
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
@@ -10068,7 +10078,14 @@ ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len)
if (lun != NULL && lun->be_lun->flags & CTL_LUN_FLAG_UNMAP) {
lbp_ptr->flags = SVPD_LBP_UNMAP | SVPD_LBP_WS16 |
SVPD_LBP_WS10 | SVPD_LBP_RZ | SVPD_LBP_ANC_SUP;
- lbp_ptr->prov_type = SVPD_LBP_THIN;
+ value = ctl_get_opt(&lun->be_lun->options, "provisioning_type");
+ if (value != NULL) {
+ if (strcmp(value, "resource") == 0)
+ lbp_ptr->prov_type = SVPD_LBP_RESOURCE;
+ else if (strcmp(value, "thin") == 0)
+ lbp_ptr->prov_type = SVPD_LBP_THIN;
+ } else
+ lbp_ptr->prov_type = SVPD_LBP_THIN;
}
ctl_set_success(ctsio);
diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h
index ba78ff0..3c47a6f 100644
--- a/sys/cam/ctl/ctl.h
+++ b/sys/cam/ctl/ctl.h
@@ -217,6 +217,7 @@ void ctl_update_opts(ctl_options_t *opts, int num_args,
struct ctl_be_arg *args);
void ctl_free_opts(ctl_options_t *opts);
char * ctl_get_opt(ctl_options_t *opts, const char *name);
+int ctl_get_opt_number(ctl_options_t *opts, const char *name, uint64_t *num);
int ctl_expand_number(const char *buf, uint64_t *num);
#endif /* _KERNEL */
diff --git a/sys/cam/ctl/ctl_backend.c b/sys/cam/ctl/ctl_backend.c
index 91576c4..86f7d3c 100644
--- a/sys/cam/ctl/ctl_backend.c
+++ b/sys/cam/ctl/ctl_backend.c
@@ -243,3 +243,14 @@ ctl_get_opt(ctl_options_t *opts, const char *name)
}
return (NULL);
}
+
+int
+ctl_get_opt_number(ctl_options_t *opts, const char *name, uint64_t *val)
+{
+ const char *value;
+
+ value = ctl_get_opt(opts, name);
+ if (value == NULL)
+ return (-2);
+ return (ctl_expand_number(value, val));
+}
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 8bf3ed0..977ac8d 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -1492,8 +1492,7 @@ daclose(struct disk *dp)
error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_QUIET_IR,
softc->disk->d_devstat);
- if (error == 0)
- softc->flags &= ~DA_FLAG_DIRTY;
+ softc->flags &= ~DA_FLAG_DIRTY;
xpt_release_ccb(ccb);
}
diff --git a/sys/cam/scsi/scsi_enc_ses.c b/sys/cam/scsi/scsi_enc_ses.c
index dfb232a..283e2e3 100644
--- a/sys/cam/scsi/scsi_enc_ses.c
+++ b/sys/cam/scsi/scsi_enc_ses.c
@@ -2672,13 +2672,13 @@ ses_get_elm_devnames(enc_softc_t *enc, encioc_elm_devnames_t *elmdn)
if (len < 0)
return (EINVAL);
- sbuf_new(&sb, elmdn->elm_devnames, len, 0);
-
cam_periph_unlock(enc->periph);
+ sbuf_new(&sb, NULL, len, SBUF_FIXEDLEN);
ses_paths_iter(enc, &enc->enc_cache.elm_map[elmdn->elm_idx],
ses_elmdevname_callback, &sb);
sbuf_finish(&sb);
elmdn->elm_names_len = sbuf_len(&sb);
+ copyout(sbuf_data(&sb), elmdn->elm_devnames, elmdn->elm_names_len + 1);
cam_periph_lock(enc->periph);
return (elmdn->elm_names_len > 0 ? 0 : ENODEV);
}
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index d7fa73b9..68412b4 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -1876,6 +1876,18 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread
break;
}
+ if (ccb->ccb_h.flags & CAM_CDB_POINTER) {
+ if (ccb->csio.cdb_len > IOCDBLEN) {
+ error = EINVAL;
+ break;
+ }
+ error = copyin(ccb->csio.cdb_io.cdb_ptr,
+ ccb->csio.cdb_io.cdb_bytes, ccb->csio.cdb_len);
+ if (error)
+ break;
+ ccb->ccb_h.flags &= ~CAM_CDB_POINTER;
+ }
+
/*
* Some CCB types, like scan bus and scan lun can only go
* through the transport layer device.
@@ -2143,6 +2155,7 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
{
struct pass_softc *softc;
struct cam_periph_map_info mapinfo;
+ uint8_t *cmd;
xpt_opcode fc;
int error;
@@ -2154,6 +2167,14 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
*/
xpt_merge_ccb(ccb, inccb);
+ if (ccb->ccb_h.flags & CAM_CDB_POINTER) {
+ cmd = __builtin_alloca(ccb->csio.cdb_len);
+ error = copyin(ccb->csio.cdb_io.cdb_ptr, cmd, ccb->csio.cdb_len);
+ if (error)
+ return (error);
+ ccb->csio.cdb_io.cdb_ptr = cmd;
+ }
+
/*
*/
ccb->ccb_h.cbfcnp = passdone;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
index 5eecc23..aad0086 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
@@ -1489,10 +1489,18 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
* objects may be dirtied in syncing context, but only if they
* were already pre-dirtied in open context.
*/
+#ifdef DEBUG
+ if (dn->dn_objset->os_dsl_dataset != NULL) {
+ rrw_enter(&dn->dn_objset->os_dsl_dataset->ds_bp_rwlock,
+ RW_READER, FTAG);
+ }
ASSERT(!dmu_tx_is_syncing(tx) ||
BP_IS_HOLE(dn->dn_objset->os_rootbp) ||
DMU_OBJECT_IS_SPECIAL(dn->dn_object) ||
dn->dn_objset->os_dsl_dataset == NULL);
+ if (dn->dn_objset->os_dsl_dataset != NULL)
+ rrw_exit(&dn->dn_objset->os_dsl_dataset->ds_bp_rwlock, FTAG);
+#endif
/*
* We make this assert for private objects as well, but after we
* check if we're already dirty. They are allowed to re-dirty
@@ -1517,12 +1525,21 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
* Don't set dirtyctx to SYNC if we're just modifying this as we
* initialize the objset.
*/
- if (dn->dn_dirtyctx == DN_UNDIRTIED &&
- !BP_IS_HOLE(dn->dn_objset->os_rootbp)) {
- dn->dn_dirtyctx =
- (dmu_tx_is_syncing(tx) ? DN_DIRTY_SYNC : DN_DIRTY_OPEN);
- ASSERT(dn->dn_dirtyctx_firstset == NULL);
- dn->dn_dirtyctx_firstset = kmem_alloc(1, KM_SLEEP);
+ if (dn->dn_dirtyctx == DN_UNDIRTIED) {
+ if (dn->dn_objset->os_dsl_dataset != NULL) {
+ rrw_enter(&dn->dn_objset->os_dsl_dataset->ds_bp_rwlock,
+ RW_READER, FTAG);
+ }
+ if (!BP_IS_HOLE(dn->dn_objset->os_rootbp)) {
+ dn->dn_dirtyctx = (dmu_tx_is_syncing(tx) ?
+ DN_DIRTY_SYNC : DN_DIRTY_OPEN);
+ ASSERT(dn->dn_dirtyctx_firstset == NULL);
+ dn->dn_dirtyctx_firstset = kmem_alloc(1, KM_SLEEP);
+ }
+ if (dn->dn_objset->os_dsl_dataset != NULL) {
+ rrw_exit(&dn->dn_objset->os_dsl_dataset->ds_bp_rwlock,
+ FTAG);
+ }
}
mutex_exit(&dn->dn_mtx);
@@ -1567,8 +1584,14 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
* this assertion only if we're not already dirty.
*/
os = dn->dn_objset;
+#ifdef DEBUG
+ if (dn->dn_objset->os_dsl_dataset != NULL)
+ rrw_enter(&os->os_dsl_dataset->ds_bp_rwlock, RW_READER, FTAG);
ASSERT(!dmu_tx_is_syncing(tx) || DMU_OBJECT_IS_SPECIAL(dn->dn_object) ||
os->os_dsl_dataset == NULL || BP_IS_HOLE(os->os_rootbp));
+ if (dn->dn_objset->os_dsl_dataset != NULL)
+ rrw_exit(&os->os_dsl_dataset->ds_bp_rwlock, FTAG);
+#endif
ASSERT(db->db.db_size != 0);
dprintf_dbuf(db, "size=%llx\n", (u_longlong_t)db->db.db_size);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
index b6ae968..f31ad2f 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
@@ -489,8 +489,10 @@ dmu_objset_from_ds(dsl_dataset_t *ds, objset_t **osp)
mutex_enter(&ds->ds_opening_lock);
if (ds->ds_objset == NULL) {
objset_t *os;
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
err = dmu_objset_open_impl(dsl_dataset_get_spa(ds),
ds, dsl_dataset_get_blkptr(ds), &os);
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
if (err == 0) {
mutex_enter(&ds->ds_lock);
@@ -876,9 +878,11 @@ dmu_objset_create_sync(void *arg, dmu_tx_t *tx)
doca->doca_cred, tx);
VERIFY0(dsl_dataset_hold_obj(pdd->dd_pool, obj, FTAG, &ds));
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
bp = dsl_dataset_get_blkptr(ds);
os = dmu_objset_create_impl(pdd->dd_pool->dp_spa,
ds, bp, doca->doca_type, tx);
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
if (doca->doca_userfunc != NULL) {
doca->doca_userfunc(os, doca->doca_userarg,
@@ -1051,7 +1055,6 @@ dmu_objset_write_ready(zio_t *zio, arc_buf_t *abuf, void *arg)
dnode_phys_t *dnp = &os->os_phys->os_meta_dnode;
ASSERT(!BP_IS_EMBEDDED(bp));
- ASSERT3P(bp, ==, os->os_rootbp);
ASSERT3U(BP_GET_TYPE(bp), ==, DMU_OT_OBJSET);
ASSERT0(BP_GET_LEVEL(bp));
@@ -1064,6 +1067,11 @@ dmu_objset_write_ready(zio_t *zio, arc_buf_t *abuf, void *arg)
bp->blk_fill = 0;
for (int i = 0; i < dnp->dn_nblkptr; i++)
bp->blk_fill += BP_GET_FILL(&dnp->dn_blkptr[i]);
+ if (os->os_dsl_dataset != NULL)
+ rrw_enter(&os->os_dsl_dataset->ds_bp_rwlock, RW_WRITER, FTAG);
+ *os->os_rootbp = *bp;
+ if (os->os_dsl_dataset != NULL)
+ rrw_exit(&os->os_dsl_dataset->ds_bp_rwlock, FTAG);
}
/* ARGSUSED */
@@ -1083,6 +1091,7 @@ dmu_objset_write_done(zio_t *zio, arc_buf_t *abuf, void *arg)
(void) dsl_dataset_block_kill(ds, bp_orig, tx, B_TRUE);
dsl_dataset_block_born(ds, bp, tx);
}
+ kmem_free(bp, sizeof (*bp));
}
/* called from dsl */
@@ -1096,6 +1105,8 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
list_t *list;
list_t *newlist = NULL;
dbuf_dirty_record_t *dr;
+ blkptr_t *blkptr_copy = kmem_alloc(sizeof (*os->os_rootbp), KM_SLEEP);
+ *blkptr_copy = *os->os_rootbp;
dprintf_ds(os->os_dsl_dataset, "txg=%llu\n", tx->tx_txg);
@@ -1123,7 +1134,7 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
dmu_write_policy(os, NULL, 0, 0, &zp);
zio = arc_write(pio, os->os_spa, tx->tx_txg,
- os->os_rootbp, os->os_phys_buf, DMU_OS_IS_L2CACHEABLE(os),
+ blkptr_copy, os->os_phys_buf, DMU_OS_IS_L2CACHEABLE(os),
&zp, dmu_objset_write_ready, NULL, NULL, dmu_objset_write_done,
os, ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
index 21ea6ef..28c6c48 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
@@ -1510,10 +1510,12 @@ dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
* If we actually created a non-clone, we need to create the
* objset in our new dataset.
*/
+ rrw_enter(&newds->ds_bp_rwlock, RW_READER, FTAG);
if (BP_IS_HOLE(dsl_dataset_get_blkptr(newds))) {
(void) dmu_objset_create_impl(dp->dp_spa,
newds, dsl_dataset_get_blkptr(newds), drrb->drr_type, tx);
}
+ rrw_exit(&newds->ds_bp_rwlock, FTAG);
drba->drba_cookie->drc_ds = newds;
@@ -1656,7 +1658,9 @@ dmu_recv_resume_begin_sync(void *arg, dmu_tx_t *tx)
dmu_buf_will_dirty(ds->ds_dbuf, tx);
dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_INCONSISTENT;
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
ASSERT(!BP_IS_HOLE(dsl_dataset_get_blkptr(ds)));
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
drba->drba_cookie->drc_ds = ds;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
index a76e74b8..fcd704f 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
@@ -40,6 +40,13 @@
#include <sys/zfeature.h>
int32_t zfs_pd_bytes_max = 50 * 1024 * 1024; /* 50MB */
+boolean_t send_holes_without_birth_time = B_TRUE;
+
+#ifdef _KERNEL
+SYSCTL_DECL(_vfs_zfs);
+SYSCTL_UINT(_vfs_zfs, OID_AUTO, send_holes_without_birth_time, CTLFLAG_RWTUN,
+ &send_holes_without_birth_time, 0, "Send holes without birth time");
+#endif
typedef struct prefetch_data {
kmutex_t pd_mtx;
@@ -254,7 +261,8 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
*
* Note that the meta-dnode cannot be reallocated.
*/
- if ((!td->td_realloc_possible ||
+ if (!send_holes_without_birth_time &&
+ (!td->td_realloc_possible ||
zb->zb_object == DMU_META_DNODE_OBJECT) &&
td->td_hole_birth_enabled_txg <= td->td_min_txg)
return (0);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
index eb203fe..3b7131e 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
@@ -312,6 +312,7 @@ dsl_dataset_evict(void *dbu)
mutex_destroy(&ds->ds_opening_lock);
mutex_destroy(&ds->ds_sendstream_lock);
refcount_destroy(&ds->ds_longholds);
+ rrw_destroy(&ds->ds_bp_rwlock);
kmem_free(ds, sizeof (dsl_dataset_t));
}
@@ -441,6 +442,7 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
+ rrw_init(&ds->ds_bp_rwlock, B_FALSE);
refcount_create(&ds->ds_longholds);
bplist_create(&ds->ds_pending_deadlist);
@@ -831,7 +833,9 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
dsl_dataset_phys(origin)->ds_compressed_bytes;
dsphys->ds_uncompressed_bytes =
dsl_dataset_phys(origin)->ds_uncompressed_bytes;
+ rrw_enter(&origin->ds_bp_rwlock, RW_READER, FTAG);
dsphys->ds_bp = dsl_dataset_phys(origin)->ds_bp;
+ rrw_exit(&origin->ds_bp_rwlock, FTAG);
/*
* Inherit flags that describe the dataset's contents
@@ -1389,7 +1393,9 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
dsphys->ds_uncompressed_bytes =
dsl_dataset_phys(ds)->ds_uncompressed_bytes;
dsphys->ds_flags = dsl_dataset_phys(ds)->ds_flags;
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
dsphys->ds_bp = dsl_dataset_phys(ds)->ds_bp;
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
dmu_buf_rele(dbuf, FTAG);
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
@@ -1981,7 +1987,9 @@ dsl_dataset_space(dsl_dataset_t *ds,
else
*availbytesp = 0;
}
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
*usedobjsp = BP_GET_FILL(&dsl_dataset_phys(ds)->ds_bp);
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
*availobjsp = DN_MAX_OBJECT - *usedobjsp;
}
@@ -1989,12 +1997,15 @@ boolean_t
dsl_dataset_modified_since_snap(dsl_dataset_t *ds, dsl_dataset_t *snap)
{
dsl_pool_t *dp = ds->ds_dir->dd_pool;
+ uint64_t birth;
ASSERT(dsl_pool_config_held(dp));
if (snap == NULL)
return (B_FALSE);
- if (dsl_dataset_phys(ds)->ds_bp.blk_birth >
- dsl_dataset_phys(snap)->ds_creation_txg) {
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
+ birth = dsl_dataset_get_blkptr(ds)->blk_birth;
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
+ if (birth > dsl_dataset_phys(snap)->ds_creation_txg) {
objset_t *os, *os_snap;
/*
* It may be that only the ZIL differs, because it was
@@ -3058,11 +3069,15 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
/* swap blkptrs */
{
+ rrw_enter(&clone->ds_bp_rwlock, RW_WRITER, FTAG);
+ rrw_enter(&origin_head->ds_bp_rwlock, RW_WRITER, FTAG);
blkptr_t tmp;
tmp = dsl_dataset_phys(origin_head)->ds_bp;
dsl_dataset_phys(origin_head)->ds_bp =
dsl_dataset_phys(clone)->ds_bp;
dsl_dataset_phys(clone)->ds_bp = tmp;
+ rrw_exit(&origin_head->ds_bp_rwlock, FTAG);
+ rrw_exit(&clone->ds_bp_rwlock, FTAG);
}
/* set dd_*_bytes */
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c
index b897176..09fa540 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c
@@ -246,7 +246,9 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
uint64_t obj;
ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
ASSERT3U(dsl_dataset_phys(ds)->ds_bp.blk_birth, <=, tx->tx_txg);
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
ASSERT(refcount_is_zero(&ds->ds_longholds));
if (defer &&
@@ -720,7 +722,9 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
ASSERT3U(dsl_dataset_phys(ds)->ds_num_children, <=, 1);
ASSERT(ds->ds_prev == NULL ||
dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj != ds->ds_object);
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
ASSERT3U(dsl_dataset_phys(ds)->ds_bp.blk_birth, <=, tx->tx_txg);
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
/* We need to log before removing it from the namespace. */
@@ -812,10 +816,12 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) ||
dsl_dataset_phys(ds)->ds_unique_bytes == used);
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
bptree_add(mos, dp->dp_bptree_obj,
&dsl_dataset_phys(ds)->ds_bp,
dsl_dataset_phys(ds)->ds_prev_snap_txg,
used, comp, uncomp, tx);
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD,
-used, -comp, -uncomp, tx);
dsl_dir_diduse_space(dp->dp_free_dir, DD_USED_HEAD,
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
index 95cf9b7..9de2d80 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -493,8 +493,10 @@ dsl_pool_create(spa_t *spa, nvlist_t *zplprops, uint64_t txg)
/* create the root objset */
VERIFY0(dsl_dataset_hold_obj(dp, obj, FTAG, &ds));
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
os = dmu_objset_create_impl(dp->dp_spa, ds,
dsl_dataset_get_blkptr(ds), DMU_OST_ZFS, tx);
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
#ifdef _KERNEL
zfs_create_fs(os, kcred, zplprops, tx);
#endif
@@ -807,7 +809,9 @@ upgrade_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg)
* The $ORIGIN can't have any data, or the accounting
* will be wrong.
*/
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
ASSERT0(dsl_dataset_phys(prev)->ds_bp.blk_birth);
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
/* The origin doesn't get attached to itself */
if (ds->ds_object == prev->ds_object) {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
index f68a6ba..4ebbc1a 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
@@ -1113,7 +1113,9 @@ dsl_scan_visitds(dsl_scan_t *scn, uint64_t dsobj, dmu_tx_t *tx)
* Iterate over the bps in this ds.
*/
dmu_buf_will_dirty(ds->ds_dbuf, tx);
+ rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
dsl_scan_visit_rootbp(scn, ds, &dsl_dataset_phys(ds)->ds_bp, tx);
+ rrw_exit(&ds->ds_bp_rwlock, FTAG);
char *dsname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
dsl_dataset_name(ds, dsname);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
index f05b2cf..977232d 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -101,9 +101,14 @@ struct objset {
zfs_redundant_metadata_type_t os_redundant_metadata;
int os_recordsize;
+ /*
+ * Pointer is constant; the blkptr it points to is protected by
+ * os_dsl_dataset->ds_bp_rwlock
+ */
+ blkptr_t *os_rootbp;
+
/* no lock needed: */
struct dmu_tx *os_synctx; /* XXX sketchy */
- blkptr_t *os_rootbp;
zil_header_t os_zil_header;
list_t os_synced_dnodes;
uint64_t os_flags;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
index 54c63b9..18466bb 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
@@ -39,6 +39,7 @@
#include <sys/zfs_context.h>
#include <sys/dsl_deadlist.h>
#include <sys/refcount.h>
+#include <sys/rrwlock.h>
#include <zfeature_common.h>
#ifdef __cplusplus
@@ -141,6 +142,7 @@ typedef struct dsl_dataset_phys {
typedef struct dsl_dataset {
dmu_buf_user_t ds_dbu;
+ rrwlock_t ds_bp_rwlock; /* Protects ds_phys->ds_bp */
/* Immutable: */
struct dsl_dir *ds_dir;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h
index 79728c1..c127788 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h
@@ -355,6 +355,8 @@ extern zil_get_data_t zfs_get_data;
extern zil_replay_func_t *zfs_replay_vector[TX_MAX_TYPE];
extern int zfsfstype;
+extern int zfs_znode_parent_and_name(znode_t *zp, znode_t **dzpp, char *buf);
+
#endif /* _KERNEL */
extern int zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index a700a5e..17c702a 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -421,7 +421,7 @@ page_busy(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
vm_page_reference(pp);
vm_page_lock(pp);
zfs_vmobject_wunlock(obj);
- vm_page_busy_sleep(pp, "zfsmwb");
+ vm_page_busy_sleep(pp, "zfsmwb", true);
zfs_vmobject_wlock(obj);
continue;
}
@@ -476,7 +476,7 @@ page_hold(vnode_t *vp, int64_t start)
vm_page_reference(pp);
vm_page_lock(pp);
zfs_vmobject_wunlock(obj);
- vm_page_busy_sleep(pp, "zfsmwb");
+ vm_page_busy_sleep(pp, "zfsmwb", true);
zfs_vmobject_wlock(obj);
continue;
}
@@ -5934,8 +5934,19 @@ zfs_vptocnp(struct vop_vptocnp_args *ap)
}
if (zp->z_id != parent || zfsvfs->z_parent == zfsvfs) {
+ char name[MAXNAMLEN + 1];
+ znode_t *dzp;
+ size_t len;
+
+ error = zfs_znode_parent_and_name(zp, &dzp, name);
+ if (error == 0) {
+ len = strlen(name);
+ *ap->a_buflen -= len;
+ bcopy(name, ap->a_buf + *ap->a_buflen, len);
+ *ap->a_vpp = ZTOV(dzp);
+ }
ZFS_EXIT(zfsvfs);
- return (vop_stdvptocnp(ap));
+ return (error);
}
ZFS_EXIT(zfsvfs);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
index c947e54..224e829 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
@@ -1936,7 +1936,6 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
mutex_destroy(&zfsvfs->z_hold_mtx[i]);
kmem_free(zfsvfs, sizeof (zfsvfs_t));
}
-
#endif /* _KERNEL */
static int
@@ -2192,3 +2191,35 @@ zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
zfs_release_sa_handle(hdl, db, FTAG);
return (error);
}
+
+#ifdef _KERNEL
+int
+zfs_znode_parent_and_name(znode_t *zp, znode_t **dzpp, char *buf)
+{
+ zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+ uint64_t parent;
+ int is_xattrdir;
+ int err;
+
+ /* Extended attributes should not be visible as regular files. */
+ if ((zp->z_pflags & ZFS_XATTR) != 0)
+ return (SET_ERROR(EINVAL));
+
+ err = zfs_obj_to_pobj(zfsvfs->z_os, zp->z_sa_hdl, zfsvfs->z_attr_table,
+ &parent, &is_xattrdir);
+ if (err != 0)
+ return (err);
+ ASSERT0(is_xattrdir);
+
+ /* No name as this is a root object. */
+ if (parent == zp->z_id)
+ return (SET_ERROR(EINVAL));
+
+ err = zap_value_search(zfsvfs->z_os, parent, zp->z_id,
+ ZFS_DIRENT_OBJ(-1ULL), buf);
+ if (err != 0)
+ return (err);
+ err = zfs_zget(zfsvfs, parent, dzpp);
+ return (err);
+}
+#endif /* _KERNEL */
diff --git a/sys/cddl/dev/fbt/arm/fbt_isa.c b/sys/cddl/dev/fbt/arm/fbt_isa.c
index 592e598..068610a 100644
--- a/sys/cddl/dev/fbt/arm/fbt_isa.c
+++ b/sys/cddl/dev/fbt/arm/fbt_isa.c
@@ -106,9 +106,6 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
return (0);
}
- if (name[0] == '_' && name[1] == '_')
- return (0);
-
instr = (uint32_t *)symval->value;
limit = (uint32_t *)(symval->value + symval->size);
diff --git a/sys/cddl/dev/fbt/fbt.c b/sys/cddl/dev/fbt/fbt.c
index 19018f9..41de379 100644
--- a/sys/cddl/dev/fbt/fbt.c
+++ b/sys/cddl/dev/fbt/fbt.c
@@ -126,10 +126,6 @@ fbt_excluded(const char *name)
return (1);
}
- /* Exclude some internal functions */
- if (name[0] == '_' && name[1] == '_')
- return (1);
-
/*
* When DTrace is built into the kernel we need to exclude
* the FBT functions from instrumentation.
diff --git a/sys/cddl/dev/fbt/powerpc/fbt_isa.c b/sys/cddl/dev/fbt/powerpc/fbt_isa.c
index 0568e55..e67e837 100644
--- a/sys/cddl/dev/fbt/powerpc/fbt_isa.c
+++ b/sys/cddl/dev/fbt/powerpc/fbt_isa.c
@@ -138,9 +138,6 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
return (0);
}
- if (name[0] == '_' && name[1] == '_')
- return (0);
-
instr = (uint32_t *) symval->value;
limit = (uint32_t *) (symval->value + symval->size);
diff --git a/sys/cddl/dev/fbt/x86/fbt_isa.c b/sys/cddl/dev/fbt/x86/fbt_isa.c
index 6639806..51cfc64 100644
--- a/sys/cddl/dev/fbt/x86/fbt_isa.c
+++ b/sys/cddl/dev/fbt/x86/fbt_isa.c
@@ -174,9 +174,6 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
return (0);
}
- if (name[0] == '_' && name[1] == '_')
- return (0);
-
size = symval->size;
instr = (uint8_t *) symval->value;
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 29d9171..797b82e 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -3062,3 +3062,10 @@ options GZIO
# BHND(4) drivers
options BHND_LOGLEVEL # Logging threshold level
+
+# evdev interface
+device evdev # input event device support
+options EVDEV_SUPPORT # evdev support in legacy drivers
+options EVDEV_DEBUG # enable event debug msgs
+device uinput # install /dev/uinput cdev
+options UINPUT_DEBUG # enable uinput debug msgs
diff --git a/sys/conf/files b/sys/conf/files
index 221337f..2dd6406 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1497,6 +1497,11 @@ dev/etherswitch/ip17x/ip17x_vlans.c optional ip17x
dev/etherswitch/miiproxy.c optional miiproxy
dev/etherswitch/rtl8366/rtl8366rb.c optional rtl8366rb
dev/etherswitch/ukswitch/ukswitch.c optional ukswitch
+dev/evdev/cdev.c optional evdev
+dev/evdev/evdev.c optional evdev
+dev/evdev/evdev_mt.c optional evdev
+dev/evdev/evdev_utils.c optional evdev
+dev/evdev/uinput.c optional evdev uinput
dev/ex/if_ex.c optional ex
dev/ex/if_ex_isa.c optional ex isa
dev/ex/if_ex_pccard.c optional ex pccard
diff --git a/sys/conf/options b/sys/conf/options
index 75244fb..52f0288 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -986,3 +986,8 @@ BHND_LOGLEVEL opt_global.h
# GPIO and child devices
GPIO_SPI_DEBUG opt_gpio.h
+
+# evdev protocol support
+EVDEV_SUPPORT opt_evdev.h
+EVDEV_DEBUG opt_evdev.h
+UINPUT_DEBUG opt_evdev.h
diff --git a/sys/dev/bxe/bxe.c b/sys/dev/bxe/bxe.c
index a5c13ea..c5daac5 100644
--- a/sys/dev/bxe/bxe.c
+++ b/sys/dev/bxe/bxe.c
@@ -27,7 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#define BXE_DRIVER_VERSION "1.78.81"
+#define BXE_DRIVER_VERSION "1.78.89"
#include "bxe.h"
#include "ecore_sp.h"
@@ -489,7 +489,14 @@ static const struct {
{ STATS_OFFSET32(mbuf_alloc_tpa),
4, STATS_FLAGS_FUNC, "mbuf_alloc_tpa"},
{ STATS_OFFSET32(tx_queue_full_return),
- 4, STATS_FLAGS_FUNC, "tx_queue_full_return"}
+ 4, STATS_FLAGS_FUNC, "tx_queue_full_return"},
+ { STATS_OFFSET32(tx_request_link_down_failures),
+ 4, STATS_FLAGS_FUNC, "tx_request_link_down_failures"},
+ { STATS_OFFSET32(bd_avail_too_less_failures),
+ 4, STATS_FLAGS_FUNC, "bd_avail_too_less_failures"},
+ { STATS_OFFSET32(tx_mq_not_empty),
+ 4, STATS_FLAGS_FUNC, "tx_mq_not_empty"}
+
};
static const struct {
@@ -602,7 +609,14 @@ static const struct {
{ Q_STATS_OFFSET32(mbuf_alloc_tpa),
4, "mbuf_alloc_tpa"},
{ Q_STATS_OFFSET32(tx_queue_full_return),
- 4, "tx_queue_full_return"}
+ 4, "tx_queue_full_return"},
+ { Q_STATS_OFFSET32(tx_request_link_down_failures),
+ 4, "tx_request_link_down_failures"},
+ { Q_STATS_OFFSET32(bd_avail_too_less_failures),
+ 4, "bd_avail_too_less_failures"},
+ { Q_STATS_OFFSET32(tx_mq_not_empty),
+ 4, "tx_mq_not_empty"}
+
};
#define BXE_NUM_ETH_STATS ARRAY_SIZE(bxe_eth_stats_arr)
@@ -5599,7 +5613,7 @@ bxe_tx_start(if_t ifp)
BXE_FP_TX_UNLOCK(fp);
}
-#if __FreeBSD_version >= 800000
+#if __FreeBSD_version >= 901504
static int
bxe_tx_mq_start_locked(struct bxe_softc *sc,
@@ -5621,11 +5635,16 @@ bxe_tx_mq_start_locked(struct bxe_softc *sc,
return (EINVAL);
}
- if (!sc->link_vars.link_up ||
- (if_getdrvflags(ifp) &
- (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) {
- if (m != NULL)
- rc = drbr_enqueue(ifp, tx_br, m);
+ if (m != NULL) {
+ rc = drbr_enqueue(ifp, tx_br, m);
+ if (rc != 0) {
+ fp->eth_q_stats.tx_soft_errors++;
+ goto bxe_tx_mq_start_locked_exit;
+ }
+ }
+
+ if (!sc->link_vars.link_up || !(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ fp->eth_q_stats.tx_request_link_down_failures++;
goto bxe_tx_mq_start_locked_exit;
}
@@ -5635,24 +5654,22 @@ bxe_tx_mq_start_locked(struct bxe_softc *sc,
fp->eth_q_stats.tx_max_drbr_queue_depth = depth;
}
- if (m == NULL) {
- /* no new work, check for pending frames */
- next = drbr_dequeue_drv(ifp, tx_br);
- } else if (drbr_needs_enqueue_drv(ifp, tx_br)) {
- /* have both new and pending work, maintain packet order */
- rc = drbr_enqueue(ifp, tx_br, m);
- if (rc != 0) {
- fp->eth_q_stats.tx_soft_errors++;
- goto bxe_tx_mq_start_locked_exit;
- }
- next = drbr_dequeue_drv(ifp, tx_br);
- } else {
- /* new work only and nothing pending */
- next = m;
- }
-
/* keep adding entries while there are frames to send */
- while (next != NULL) {
+ while ((next = drbr_peek(ifp, tx_br)) != NULL) {
+ /* handle any completions if we're running low */
+ tx_bd_avail = bxe_tx_avail(sc, fp);
+ if (tx_bd_avail < BXE_TX_CLEANUP_THRESHOLD) {
+ /* bxe_txeof will set IFF_DRV_OACTIVE appropriately */
+ bxe_txeof(sc, fp);
+ tx_bd_avail = bxe_tx_avail(sc, fp);
+ if (tx_bd_avail < (BXE_TSO_MAX_SEGMENTS + 1)) {
+ fp->eth_q_stats.bd_avail_too_less_failures++;
+ m_freem(next);
+ drbr_advance(ifp, tx_br);
+ rc = ENOBUFS;
+ break;
+ }
+ }
/* the mbuf now belongs to us */
fp->eth_q_stats.mbuf_alloc_tx++;
@@ -5668,11 +5685,11 @@ bxe_tx_mq_start_locked(struct bxe_softc *sc,
if (next != NULL) {
/* mark the TX queue as full and save the frame */
if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
- /* XXX this may reorder the frame */
- rc = drbr_enqueue(ifp, tx_br, next);
+ drbr_putback(ifp, tx_br, next);
fp->eth_q_stats.mbuf_alloc_tx--;
fp->eth_q_stats.tx_frames_deferred++;
- }
+ } else
+ drbr_advance(ifp, tx_br);
/* stop looking for more work */
break;
@@ -5684,18 +5701,7 @@ bxe_tx_mq_start_locked(struct bxe_softc *sc,
/* send a copy of the frame to any BPF listeners */
if_etherbpfmtap(ifp, next);
- tx_bd_avail = bxe_tx_avail(sc, fp);
-
- /* handle any completions if we're running low */
- if (tx_bd_avail < BXE_TX_CLEANUP_THRESHOLD) {
- /* bxe_txeof will set IFF_DRV_OACTIVE appropriately */
- bxe_txeof(sc, fp);
- if (if_getdrvflags(ifp) & IFF_DRV_OACTIVE) {
- break;
- }
- }
-
- next = drbr_dequeue_drv(ifp, tx_br);
+ drbr_advance(ifp, tx_br);
}
/* all TX packets were dequeued and/or the tx ring is full */
@@ -5705,10 +5711,28 @@ bxe_tx_mq_start_locked(struct bxe_softc *sc,
}
bxe_tx_mq_start_locked_exit:
+ /* If we didn't drain the drbr, enqueue a task in the future to do it. */
+ if (!drbr_empty(ifp, tx_br)) {
+ fp->eth_q_stats.tx_mq_not_empty++;
+ taskqueue_enqueue_timeout(fp->tq, &fp->tx_timeout_task, 1);
+ }
return (rc);
}
+static void
+bxe_tx_mq_start_deferred(void *arg,
+ int pending)
+{
+ struct bxe_fastpath *fp = (struct bxe_fastpath *)arg;
+ struct bxe_softc *sc = fp->sc;
+ if_t ifp = sc->ifp;
+
+ BXE_FP_TX_LOCK(fp);
+ bxe_tx_mq_start_locked(sc, ifp, fp, NULL);
+ BXE_FP_TX_UNLOCK(fp);
+}
+
/* Multiqueue (TSS) dispatch routine. */
static int
bxe_tx_mq_start(struct ifnet *ifp,
@@ -5730,8 +5754,10 @@ bxe_tx_mq_start(struct ifnet *ifp,
if (BXE_FP_TX_TRYLOCK(fp)) {
rc = bxe_tx_mq_start_locked(sc, ifp, fp, m);
BXE_FP_TX_UNLOCK(fp);
- } else
+ } else {
rc = drbr_enqueue(ifp, fp->tx_br, m);
+ taskqueue_enqueue(fp->tq, &fp->tx_task);
+ }
return (rc);
}
@@ -5766,7 +5792,7 @@ bxe_mq_flush(struct ifnet *ifp)
if_qflush(ifp);
}
-#endif /* FreeBSD_version >= 800000 */
+#endif /* FreeBSD_version >= 901504 */
static uint16_t
bxe_cid_ilt_lines(struct bxe_softc *sc)
@@ -6126,7 +6152,7 @@ bxe_free_fp_buffers(struct bxe_softc *sc)
for (i = 0; i < sc->num_queues; i++) {
fp = &sc->fp[i];
-#if __FreeBSD_version >= 800000
+#if __FreeBSD_version >= 901504
if (fp->tx_br != NULL) {
/* just in case bxe_mq_flush() wasn't called */
if (mtx_initialized(&fp->tx_mtx)) {
@@ -6953,6 +6979,8 @@ bxe_link_attn(struct bxe_softc *sc)
uint32_t pause_enabled = 0;
struct host_port_stats *pstats;
int cmng_fns;
+ struct bxe_fastpath *fp;
+ int i;
/* Make sure that we are synced with the current statistics */
bxe_stats_handle(sc, STATS_EVENT_STOP);
@@ -6984,6 +7012,12 @@ bxe_link_attn(struct bxe_softc *sc)
if (sc->state == BXE_STATE_OPEN) {
bxe_stats_handle(sc, STATS_EVENT_LINK_UP);
}
+
+ /* Restart tx when the link comes back. */
+ FOR_EACH_ETH_QUEUE(sc, i) {
+ fp = &sc->fp[i];
+ taskqueue_enqueue(fp->tq, &fp->tx_task);
+ }
}
if (sc->link_vars.link_up && sc->link_vars.line_speed) {
@@ -9035,6 +9069,10 @@ bxe_interrupt_detach(struct bxe_softc *sc)
fp = &sc->fp[i];
if (fp->tq) {
taskqueue_drain(fp->tq, &fp->tq_task);
+ taskqueue_drain(fp->tq, &fp->tx_task);
+ while (taskqueue_cancel_timeout(fp->tq, &fp->tx_timeout_task,
+ NULL))
+ taskqueue_drain_timeout(fp->tq, &fp->tx_timeout_task);
taskqueue_free(fp->tq);
fp->tq = NULL;
}
@@ -9067,9 +9105,9 @@ bxe_interrupt_attach(struct bxe_softc *sc)
snprintf(sc->sp_tq_name, sizeof(sc->sp_tq_name),
"bxe%d_sp_tq", sc->unit);
TASK_INIT(&sc->sp_tq_task, 0, bxe_handle_sp_tq, sc);
- sc->sp_tq = taskqueue_create_fast(sc->sp_tq_name, M_NOWAIT,
- taskqueue_thread_enqueue,
- &sc->sp_tq);
+ sc->sp_tq = taskqueue_create(sc->sp_tq_name, M_NOWAIT,
+ taskqueue_thread_enqueue,
+ &sc->sp_tq);
taskqueue_start_threads(&sc->sp_tq, 1, PWAIT, /* lower priority */
"%s", sc->sp_tq_name);
@@ -9079,9 +9117,12 @@ bxe_interrupt_attach(struct bxe_softc *sc)
snprintf(fp->tq_name, sizeof(fp->tq_name),
"bxe%d_fp%d_tq", sc->unit, i);
TASK_INIT(&fp->tq_task, 0, bxe_handle_fp_tq, fp);
- fp->tq = taskqueue_create_fast(fp->tq_name, M_NOWAIT,
- taskqueue_thread_enqueue,
- &fp->tq);
+ TASK_INIT(&fp->tx_task, 0, bxe_tx_mq_start_deferred, fp);
+ fp->tq = taskqueue_create(fp->tq_name, M_NOWAIT,
+ taskqueue_thread_enqueue,
+ &fp->tq);
+ TIMEOUT_TASK_INIT(fp->tq, &fp->tx_timeout_task, 0,
+ bxe_tx_mq_start_deferred, fp);
taskqueue_start_threads(&fp->tq, 1, PI_NET, /* higher priority */
"%s", fp->tq_name);
}
@@ -12114,8 +12155,6 @@ static void
bxe_periodic_callout_func(void *xsc)
{
struct bxe_softc *sc = (struct bxe_softc *)xsc;
- struct bxe_fastpath *fp;
- uint16_t tx_bd_avail;
int i;
if (!BXE_CORE_TRYLOCK(sc)) {
@@ -12136,49 +12175,8 @@ bxe_periodic_callout_func(void *xsc)
BLOGW(sc, "periodic callout exit (state=0x%x)\n", sc->state);
BXE_CORE_UNLOCK(sc);
return;
- }
-
-#if __FreeBSD_version >= 800000
-
- FOR_EACH_QUEUE(sc, i) {
- fp = &sc->fp[i];
-
- if (BXE_FP_TX_TRYLOCK(fp)) {
- if_t ifp = sc->ifp;
- /*
- * If interface was stopped due to unavailable
- * bds, try to process some tx completions
- */
- (void) bxe_txeof(sc, fp);
-
- tx_bd_avail = bxe_tx_avail(sc, fp);
- if (tx_bd_avail >= BXE_TX_CLEANUP_THRESHOLD) {
- bxe_tx_mq_start_locked(sc, ifp, fp, NULL);
- }
- BXE_FP_TX_UNLOCK(fp);
- }
- }
-
-#else
-
- fp = &sc->fp[0];
- if (BXE_FP_TX_TRYLOCK(fp)) {
- struct ifnet *ifp = sc->ifnet;
- /*
- * If interface was stopped due to unavailable
- * bds, try to process some tx completions
- */
- (void) bxe_txeof(sc, fp);
-
- tx_bd_avail = bxe_tx_avail(sc, fp);
- if (tx_bd_avail >= BXE_TX_CLEANUP_THRESHOLD) {
- bxe_tx_start_locked(sc, ifp, fp);
}
-
- BXE_FP_TX_UNLOCK(fp);
- }
-#endif /* #if __FreeBSD_version >= 800000 */
/* Check for TX timeouts on any fastpath. */
FOR_EACH_QUEUE(sc, i) {
@@ -12656,7 +12654,7 @@ bxe_init_ifnet(struct bxe_softc *sc)
if_setioctlfn(ifp, bxe_ioctl);
if_setstartfn(ifp, bxe_tx_start);
if_setgetcounterfn(ifp, bxe_get_counter);
-#if __FreeBSD_version >= 800000
+#if __FreeBSD_version >= 901504
if_settransmitfn(ifp, bxe_tx_mq_start);
if_setqflushfn(ifp, bxe_mq_flush);
#endif
@@ -15699,7 +15697,7 @@ bxe_add_sysctls(struct bxe_softc *sc)
static int
bxe_alloc_buf_rings(struct bxe_softc *sc)
{
-#if __FreeBSD_version >= 800000
+#if __FreeBSD_version >= 901504
int i;
struct bxe_fastpath *fp;
@@ -15720,7 +15718,7 @@ bxe_alloc_buf_rings(struct bxe_softc *sc)
static void
bxe_free_buf_rings(struct bxe_softc *sc)
{
-#if __FreeBSD_version >= 800000
+#if __FreeBSD_version >= 901504
int i;
struct bxe_fastpath *fp;
diff --git a/sys/dev/bxe/bxe.h b/sys/dev/bxe/bxe.h
index 40c9a36..3424ce8 100644
--- a/sys/dev/bxe/bxe.h
+++ b/sys/dev/bxe/bxe.h
@@ -644,6 +644,9 @@ struct bxe_fastpath {
struct taskqueue *tq;
char tq_name[32];
+ struct task tx_task;
+ struct timeout_task tx_timeout_task;
+
/* ethernet client ID (each fastpath set of RX/TX/CQE is a client) */
uint8_t cl_id;
#define FP_CL_ID(fp) (fp->cl_id)
@@ -2300,7 +2303,8 @@ void bxe_dump_mbuf_data(struct bxe_softc *sc, char *pTag,
extern int bxe_grc_dump(struct bxe_softc *sc);
#if __FreeBSD_version >= 800000
-#if __FreeBSD_version >= 1000000
+#if (__FreeBSD_version >= 1001513 && __FreeBSD_version < 1100000) ||\
+ __FreeBSD_version >= 1100048
#define BXE_SET_FLOWID(m) M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE)
#define BXE_VALID_FLOWID(m) (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE)
#else
diff --git a/sys/dev/bxe/bxe_stats.h b/sys/dev/bxe/bxe_stats.h
index a0f5792..ad8cc13 100644
--- a/sys/dev/bxe/bxe_stats.h
+++ b/sys/dev/bxe/bxe_stats.h
@@ -266,6 +266,10 @@ struct bxe_eth_stats {
/* num. of times tx queue full occurred */
uint32_t tx_queue_full_return;
+ /* debug stats */
+ uint32_t tx_request_link_down_failures;
+ uint32_t bd_avail_too_less_failures;
+ uint32_t tx_mq_not_empty;
};
@@ -372,6 +376,11 @@ struct bxe_eth_q_stats {
/* num. of times tx queue full occurred */
uint32_t tx_queue_full_return;
+
+ /* debug stats */
+ uint32_t tx_request_link_down_failures;
+ uint32_t bd_avail_too_less_failures;
+ uint32_t tx_mq_not_empty;
};
struct bxe_eth_stats_old {
diff --git a/sys/dev/drm2/i915/i915_gem.c b/sys/dev/drm2/i915/i915_gem.c
index 2e75623..6e9a86c 100644
--- a/sys/dev/drm2/i915/i915_gem.c
+++ b/sys/dev/drm2/i915/i915_gem.c
@@ -1533,7 +1533,7 @@ retry:
DRM_UNLOCK(dev);
vm_page_lock(page);
VM_OBJECT_WUNLOCK(vm_obj);
- vm_page_busy_sleep(page, "915pee");
+ vm_page_busy_sleep(page, "915pee", false);
goto retry;
}
goto have_page;
@@ -1575,7 +1575,7 @@ retry:
DRM_UNLOCK(dev);
vm_page_lock(page);
VM_OBJECT_WUNLOCK(vm_obj);
- vm_page_busy_sleep(page, "915pbs");
+ vm_page_busy_sleep(page, "915pbs", false);
goto retry;
}
if (vm_page_insert(page, vm_obj, OFF_TO_IDX(offset))) {
diff --git a/sys/dev/drm2/ttm/ttm_bo_vm.c b/sys/dev/drm2/ttm/ttm_bo_vm.c
index 438077b..60bf8e2 100644
--- a/sys/dev/drm2/ttm/ttm_bo_vm.c
+++ b/sys/dev/drm2/ttm/ttm_bo_vm.c
@@ -236,7 +236,7 @@ reserve:
if (vm_page_busied(m)) {
vm_page_lock(m);
VM_OBJECT_WUNLOCK(vm_obj);
- vm_page_busy_sleep(m, "ttmpbs");
+ vm_page_busy_sleep(m, "ttmpbs", false);
VM_OBJECT_WLOCK(vm_obj);
ttm_mem_io_unlock(man);
ttm_bo_unreserve(bo);
diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c
index 55b8310..717ff2a 100644
--- a/sys/dev/e1000/if_lem.c
+++ b/sys/dev/e1000/if_lem.c
@@ -591,8 +591,16 @@ lem_attach(device_t dev)
}
#endif /* NIC_PARAVIRT */
- tsize = roundup2(adapter->num_tx_desc * sizeof(struct e1000_tx_desc),
- EM_DBA_ALIGN);
+ /*
+ * It seems that the descriptor DMA engine on some PCI cards
+ * fetches memory past the end of the last descriptor in the
+ * ring. These reads are problematic when VT-d (DMAR) busdma
+ * is used. Allocate the scratch space to avoid getting
+ * faults from DMAR, by requesting scratch memory for one more
+ * descriptor.
+ */
+ tsize = roundup2((adapter->num_tx_desc + 1) *
+ sizeof(struct e1000_tx_desc), EM_DBA_ALIGN);
/* Allocate Transmit Descriptor ring */
if (lem_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) {
@@ -603,8 +611,11 @@ lem_attach(device_t dev)
adapter->tx_desc_base =
(struct e1000_tx_desc *)adapter->txdma.dma_vaddr;
- rsize = roundup2(adapter->num_rx_desc * sizeof(struct e1000_rx_desc),
- EM_DBA_ALIGN);
+ /*
+ * See comment above txdma allocation for rationale behind +1.
+ */
+ rsize = roundup2((adapter->num_rx_desc + 1) *
+ sizeof(struct e1000_rx_desc), EM_DBA_ALIGN);
/* Allocate Receive Descriptor ring */
if (lem_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) {
diff --git a/sys/dev/evdev/cdev.c b/sys/dev/evdev/cdev.c
new file mode 100644
index 0000000..fb81ace
--- /dev/null
+++ b/sys/dev/evdev/cdev.c
@@ -0,0 +1,860 @@
+/*-
+ * Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
+ * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
+ * 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$
+ */
+
+#include "opt_evdev.h"
+
+#include <sys/types.h>
+#include <sys/bitstring.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/proc.h>
+#include <sys/poll.h>
+#include <sys/filio.h>
+#include <sys/fcntl.h>
+#include <sys/selinfo.h>
+#include <sys/malloc.h>
+#include <sys/time.h>
+
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/evdev_private.h>
+
+#ifdef EVDEV_DEBUG
+#define debugf(client, fmt, args...) printf("evdev cdev: "fmt"\n", ##args)
+#else
+#define debugf(client, fmt, args...)
+#endif
+
+#define DEF_RING_REPORTS 8
+
+static d_open_t evdev_open;
+static d_read_t evdev_read;
+static d_write_t evdev_write;
+static d_ioctl_t evdev_ioctl;
+static d_poll_t evdev_poll;
+static d_kqfilter_t evdev_kqfilter;
+
+static int evdev_kqread(struct knote *kn, long hint);
+static void evdev_kqdetach(struct knote *kn);
+static void evdev_dtor(void *);
+static int evdev_ioctl_eviocgbit(struct evdev_dev *, int, int, caddr_t);
+static void evdev_client_filter_queue(struct evdev_client *, uint16_t);
+
+static struct cdevsw evdev_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = evdev_open,
+ .d_read = evdev_read,
+ .d_write = evdev_write,
+ .d_ioctl = evdev_ioctl,
+ .d_poll = evdev_poll,
+ .d_kqfilter = evdev_kqfilter,
+ .d_name = "evdev",
+};
+
+static struct filterops evdev_cdev_filterops = {
+ .f_isfd = 1,
+ .f_attach = NULL,
+ .f_detach = evdev_kqdetach,
+ .f_event = evdev_kqread,
+};
+
+static int
+evdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct evdev_dev *evdev = dev->si_drv1;
+ struct evdev_client *client;
+ size_t buffer_size;
+ int ret;
+
+ if (evdev == NULL)
+ return (ENODEV);
+
+ /* Initialize client structure */
+ buffer_size = evdev->ev_report_size * DEF_RING_REPORTS;
+ client = malloc(offsetof(struct evdev_client, ec_buffer) +
+ sizeof(struct input_event) * buffer_size,
+ M_EVDEV, M_WAITOK | M_ZERO);
+
+ /* Initialize ring buffer */
+ client->ec_buffer_size = buffer_size;
+ client->ec_buffer_head = 0;
+ client->ec_buffer_tail = 0;
+ client->ec_buffer_ready = 0;
+
+ client->ec_evdev = evdev;
+ mtx_init(&client->ec_buffer_mtx, "evclient", "evdev", MTX_DEF);
+ knlist_init_mtx(&client->ec_selp.si_note, &client->ec_buffer_mtx);
+
+ /* Avoid race with evdev_unregister */
+ EVDEV_LOCK(evdev);
+ if (dev->si_drv1 == NULL)
+ ret = ENODEV;
+ else
+ ret = evdev_register_client(evdev, client);
+
+ if (ret != 0)
+ evdev_revoke_client(client);
+ /*
+ * Unlock evdev here because non-sleepable lock held
+ * while calling devfs_set_cdevpriv upsets WITNESS
+ */
+ EVDEV_UNLOCK(evdev);
+
+ if (!ret)
+ ret = devfs_set_cdevpriv(client, evdev_dtor);
+
+ if (ret != 0) {
+ debugf(client, "cannot register evdev client");
+ evdev_dtor(client);
+ }
+
+ return (ret);
+}
+
+static void
+evdev_dtor(void *data)
+{
+ struct evdev_client *client = (struct evdev_client *)data;
+
+ EVDEV_LOCK(client->ec_evdev);
+ if (!client->ec_revoked)
+ evdev_dispose_client(client->ec_evdev, client);
+ EVDEV_UNLOCK(client->ec_evdev);
+
+ knlist_clear(&client->ec_selp.si_note, 0);
+ seldrain(&client->ec_selp);
+ knlist_destroy(&client->ec_selp.si_note);
+ funsetown(&client->ec_sigio);
+ mtx_destroy(&client->ec_buffer_mtx);
+ free(client, M_EVDEV);
+}
+
+static int
+evdev_read(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ struct evdev_client *client;
+ struct input_event *event;
+ int ret = 0;
+ int remaining;
+
+ ret = devfs_get_cdevpriv((void **)&client);
+ if (ret != 0)
+ return (ret);
+
+ debugf(client, "read %zd bytes by thread %d", uio->uio_resid,
+ uio->uio_td->td_tid);
+
+ if (client->ec_revoked)
+ return (ENODEV);
+
+ /* Zero-sized reads are allowed for error checking */
+ if (uio->uio_resid != 0 && uio->uio_resid < sizeof(struct input_event))
+ return (EINVAL);
+
+ remaining = uio->uio_resid / sizeof(struct input_event);
+
+ EVDEV_CLIENT_LOCKQ(client);
+
+ if (EVDEV_CLIENT_EMPTYQ(client)) {
+ if (ioflag & O_NONBLOCK)
+ ret = EWOULDBLOCK;
+ else {
+ if (remaining != 0) {
+ client->ec_blocked = true;
+ ret = mtx_sleep(client, &client->ec_buffer_mtx,
+ PCATCH, "evread", 0);
+ }
+ }
+ }
+
+ while (ret == 0 && !EVDEV_CLIENT_EMPTYQ(client) && remaining > 0) {
+ event = &client->ec_buffer[client->ec_buffer_head];
+ client->ec_buffer_head =
+ (client->ec_buffer_head + 1) % client->ec_buffer_size;
+ remaining--;
+
+ EVDEV_CLIENT_UNLOCKQ(client);
+ ret = uiomove(event, sizeof(struct input_event), uio);
+ EVDEV_CLIENT_LOCKQ(client);
+ }
+
+ EVDEV_CLIENT_UNLOCKQ(client);
+
+ return (ret);
+}
+
+static int
+evdev_write(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ struct evdev_dev *evdev = dev->si_drv1;
+ struct evdev_client *client;
+ struct input_event event;
+ int ret = 0;
+
+ ret = devfs_get_cdevpriv((void **)&client);
+ if (ret != 0)
+ return (ret);
+
+ debugf(client, "write %zd bytes by thread %d", uio->uio_resid,
+ uio->uio_td->td_tid);
+
+ if (client->ec_revoked || evdev == NULL)
+ return (ENODEV);
+
+ if (uio->uio_resid % sizeof(struct input_event) != 0) {
+ debugf(client, "write size not multiple of input_event size");
+ return (EINVAL);
+ }
+
+ while (uio->uio_resid > 0 && ret == 0) {
+ ret = uiomove(&event, sizeof(struct input_event), uio);
+ if (ret == 0)
+ ret = evdev_inject_event(evdev, event.type, event.code,
+ event.value);
+ }
+
+ return (ret);
+}
+
+static int
+evdev_poll(struct cdev *dev, int events, struct thread *td)
+{
+ struct evdev_client *client;
+ int ret;
+ int revents = 0;
+
+ ret = devfs_get_cdevpriv((void **)&client);
+ if (ret != 0)
+ return (POLLNVAL);
+
+ debugf(client, "poll by thread %d", td->td_tid);
+
+ if (client->ec_revoked)
+ return (POLLHUP);
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ EVDEV_CLIENT_LOCKQ(client);
+ if (!EVDEV_CLIENT_EMPTYQ(client))
+ revents = events & (POLLIN | POLLRDNORM);
+ else {
+ client->ec_selected = true;
+ selrecord(td, &client->ec_selp);
+ }
+ EVDEV_CLIENT_UNLOCKQ(client);
+ }
+
+ return (revents);
+}
+
+static int
+evdev_kqfilter(struct cdev *dev, struct knote *kn)
+{
+ struct evdev_client *client;
+ int ret;
+
+ ret = devfs_get_cdevpriv((void **)&client);
+ if (ret != 0)
+ return (ret);
+
+ if (client->ec_revoked)
+ return (ENODEV);
+
+ switch(kn->kn_filter) {
+ case EVFILT_READ:
+ kn->kn_fop = &evdev_cdev_filterops;
+ break;
+ default:
+ return(EINVAL);
+ }
+ kn->kn_hook = (caddr_t)client;
+
+ knlist_add(&client->ec_selp.si_note, kn, 0);
+ return (0);
+}
+
+static int
+evdev_kqread(struct knote *kn, long hint)
+{
+ struct evdev_client *client;
+ int ret;
+
+ client = (struct evdev_client *)kn->kn_hook;
+
+ EVDEV_CLIENT_LOCKQ_ASSERT(client);
+
+ if (client->ec_revoked) {
+ kn->kn_flags |= EV_EOF;
+ ret = 1;
+ } else {
+ kn->kn_data = EVDEV_CLIENT_SIZEQ(client) *
+ sizeof(struct input_event);
+ ret = !EVDEV_CLIENT_EMPTYQ(client);
+ }
+ return (ret);
+}
+
+static void
+evdev_kqdetach(struct knote *kn)
+{
+ struct evdev_client *client;
+
+ client = (struct evdev_client *)kn->kn_hook;
+ knlist_remove(&client->ec_selp.si_note, kn, 0);
+}
+
+static int
+evdev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
+ struct thread *td)
+{
+ struct evdev_dev *evdev = dev->si_drv1;
+ struct evdev_client *client;
+ struct input_keymap_entry *ke;
+ int ret, len, limit, type_num;
+ uint32_t code;
+ size_t nvalues;
+
+ ret = devfs_get_cdevpriv((void **)&client);
+ if (ret != 0)
+ return (ret);
+
+ if (client->ec_revoked || evdev == NULL)
+ return (ENODEV);
+
+ /* file I/O ioctl handling */
+ switch (cmd) {
+ case FIOSETOWN:
+ return (fsetown(*(int *)data, &client->ec_sigio));
+
+ case FIOGETOWN:
+ *(int *)data = fgetown(&client->ec_sigio);
+ return (0);
+
+ case FIONBIO:
+ return (0);
+
+ case FIOASYNC:
+ if (*(int *)data)
+ client->ec_async = true;
+ else
+ client->ec_async = false;
+
+ return (0);
+
+ case FIONREAD:
+ EVDEV_CLIENT_LOCKQ(client);
+ *(int *)data =
+ EVDEV_CLIENT_SIZEQ(client) * sizeof(struct input_event);
+ EVDEV_CLIENT_UNLOCKQ(client);
+ return (0);
+ }
+
+ len = IOCPARM_LEN(cmd);
+ debugf(client, "ioctl called: cmd=0x%08lx, data=%p", cmd, data);
+
+ /* evdev fixed-length ioctls handling */
+ switch (cmd) {
+ case EVIOCGVERSION:
+ *(int *)data = EV_VERSION;
+ return (0);
+
+ case EVIOCGID:
+ debugf(client, "EVIOCGID: bus=%d vendor=0x%04x product=0x%04x",
+ evdev->ev_id.bustype, evdev->ev_id.vendor,
+ evdev->ev_id.product);
+ memcpy(data, &evdev->ev_id, sizeof(struct input_id));
+ return (0);
+
+ case EVIOCGREP:
+ if (!evdev_event_supported(evdev, EV_REP))
+ return (ENOTSUP);
+
+ memcpy(data, evdev->ev_rep, sizeof(evdev->ev_rep));
+ return (0);
+
+ case EVIOCSREP:
+ if (!evdev_event_supported(evdev, EV_REP))
+ return (ENOTSUP);
+
+ evdev_inject_event(evdev, EV_REP, REP_DELAY, ((int *)data)[0]);
+ evdev_inject_event(evdev, EV_REP, REP_PERIOD,
+ ((int *)data)[1]);
+ return (0);
+
+ case EVIOCGKEYCODE:
+ /* Fake unsupported ioctl */
+ return (0);
+
+ case EVIOCGKEYCODE_V2:
+ if (evdev->ev_methods == NULL ||
+ evdev->ev_methods->ev_get_keycode == NULL)
+ return (ENOTSUP);
+
+ ke = (struct input_keymap_entry *)data;
+ evdev->ev_methods->ev_get_keycode(evdev, evdev->ev_softc, ke);
+ return (0);
+
+ case EVIOCSKEYCODE:
+ /* Fake unsupported ioctl */
+ return (0);
+
+ case EVIOCSKEYCODE_V2:
+ if (evdev->ev_methods == NULL ||
+ evdev->ev_methods->ev_set_keycode == NULL)
+ return (ENOTSUP);
+
+ ke = (struct input_keymap_entry *)data;
+ evdev->ev_methods->ev_set_keycode(evdev, evdev->ev_softc, ke);
+ return (0);
+
+ case EVIOCGABS(0) ... EVIOCGABS(ABS_MAX):
+ if (evdev->ev_absinfo == NULL)
+ return (EINVAL);
+
+ memcpy(data, &evdev->ev_absinfo[cmd - EVIOCGABS(0)],
+ sizeof(struct input_absinfo));
+ return (0);
+
+ case EVIOCSABS(0) ... EVIOCSABS(ABS_MAX):
+ if (evdev->ev_absinfo == NULL)
+ return (EINVAL);
+
+ code = cmd - EVIOCSABS(0);
+ /* mt-slot number can not be changed */
+ if (code == ABS_MT_SLOT)
+ return (EINVAL);
+
+ EVDEV_LOCK(evdev);
+ evdev_set_absinfo(evdev, code, (struct input_absinfo *)data);
+ EVDEV_UNLOCK(evdev);
+ return (0);
+
+ case EVIOCSFF:
+ case EVIOCRMFF:
+ case EVIOCGEFFECTS:
+ /* Fake unsupported ioctls */
+ return (0);
+
+ case EVIOCGRAB:
+ EVDEV_LOCK(evdev);
+ if (*(int *)data)
+ ret = evdev_grab_client(evdev, client);
+ else
+ ret = evdev_release_client(evdev, client);
+ EVDEV_UNLOCK(evdev);
+ return (ret);
+
+ case EVIOCREVOKE:
+ if (*(int *)data != 0)
+ return (EINVAL);
+
+ EVDEV_LOCK(evdev);
+ if (dev->si_drv1 != NULL && !client->ec_revoked) {
+ evdev_dispose_client(evdev, client);
+ evdev_revoke_client(client);
+ }
+ EVDEV_UNLOCK(evdev);
+ return (0);
+
+ case EVIOCSCLOCKID:
+ switch (*(int *)data) {
+ case CLOCK_REALTIME:
+ client->ec_clock_id = EV_CLOCK_REALTIME;
+ return (0);
+ case CLOCK_MONOTONIC:
+ client->ec_clock_id = EV_CLOCK_MONOTONIC;
+ return (0);
+ default:
+ return (EINVAL);
+ }
+ }
+
+ /* evdev variable-length ioctls handling */
+ switch (IOCBASECMD(cmd)) {
+ case EVIOCGNAME(0):
+ strlcpy(data, evdev->ev_name, len);
+ return (0);
+
+ case EVIOCGPHYS(0):
+ if (evdev->ev_shortname[0] == 0)
+ return (ENOENT);
+
+ strlcpy(data, evdev->ev_shortname, len);
+ return (0);
+
+ case EVIOCGUNIQ(0):
+ if (evdev->ev_serial[0] == 0)
+ return (ENOENT);
+
+ strlcpy(data, evdev->ev_serial, len);
+ return (0);
+
+ case EVIOCGPROP(0):
+ limit = MIN(len, bitstr_size(INPUT_PROP_CNT));
+ memcpy(data, evdev->ev_prop_flags, limit);
+ return (0);
+
+ case EVIOCGMTSLOTS(0):
+ if (evdev->ev_mt == NULL)
+ return (EINVAL);
+ if (len < sizeof(uint32_t))
+ return (EINVAL);
+ code = *(uint32_t *)data;
+ if (!ABS_IS_MT(code))
+ return (EINVAL);
+
+ nvalues =
+ MIN(len / sizeof(int32_t) - 1, MAXIMAL_MT_SLOT(evdev) + 1);
+ for (int i = 0; i < nvalues; i++)
+ ((int32_t *)data)[i + 1] =
+ evdev_get_mt_value(evdev, i, code);
+ return (0);
+
+ case EVIOCGKEY(0):
+ limit = MIN(len, bitstr_size(KEY_CNT));
+ EVDEV_LOCK(evdev);
+ evdev_client_filter_queue(client, EV_KEY);
+ memcpy(data, evdev->ev_key_states, limit);
+ EVDEV_UNLOCK(evdev);
+ return (0);
+
+ case EVIOCGLED(0):
+ limit = MIN(len, bitstr_size(LED_CNT));
+ EVDEV_LOCK(evdev);
+ evdev_client_filter_queue(client, EV_LED);
+ memcpy(data, evdev->ev_led_states, limit);
+ EVDEV_UNLOCK(evdev);
+ return (0);
+
+ case EVIOCGSND(0):
+ limit = MIN(len, bitstr_size(SND_CNT));
+ EVDEV_LOCK(evdev);
+ evdev_client_filter_queue(client, EV_SND);
+ memcpy(data, evdev->ev_snd_states, limit);
+ EVDEV_UNLOCK(evdev);
+ return (0);
+
+ case EVIOCGSW(0):
+ limit = MIN(len, bitstr_size(SW_CNT));
+ EVDEV_LOCK(evdev);
+ evdev_client_filter_queue(client, EV_SW);
+ memcpy(data, evdev->ev_sw_states, limit);
+ EVDEV_UNLOCK(evdev);
+ return (0);
+
+ case EVIOCGBIT(0, 0) ... EVIOCGBIT(EV_MAX, 0):
+ type_num = IOCBASECMD(cmd) - EVIOCGBIT(0, 0);
+ debugf(client, "EVIOCGBIT(%d): data=%p, len=%d", type_num,
+ data, len);
+ return (evdev_ioctl_eviocgbit(evdev, type_num, len, data));
+ }
+
+ return (EINVAL);
+}
+
+static int
+evdev_ioctl_eviocgbit(struct evdev_dev *evdev, int type, int len, caddr_t data)
+{
+ unsigned long *bitmap;
+ int limit;
+
+ switch (type) {
+ case 0:
+ bitmap = evdev->ev_type_flags;
+ limit = EV_CNT;
+ break;
+ case EV_KEY:
+ bitmap = evdev->ev_key_flags;
+ limit = KEY_CNT;
+ break;
+ case EV_REL:
+ bitmap = evdev->ev_rel_flags;
+ limit = REL_CNT;
+ break;
+ case EV_ABS:
+ bitmap = evdev->ev_abs_flags;
+ limit = ABS_CNT;
+ break;
+ case EV_MSC:
+ bitmap = evdev->ev_msc_flags;
+ limit = MSC_CNT;
+ break;
+ case EV_LED:
+ bitmap = evdev->ev_led_flags;
+ limit = LED_CNT;
+ break;
+ case EV_SND:
+ bitmap = evdev->ev_snd_flags;
+ limit = SND_CNT;
+ break;
+ case EV_SW:
+ bitmap = evdev->ev_sw_flags;
+ limit = SW_CNT;
+ break;
+ case EV_FF:
+ /*
+ * We don't support EV_FF now, so let's
+ * just fake it returning only zeros.
+ */
+ bzero(data, len);
+ return (0);
+ default:
+ return (ENOTTY);
+ }
+
+ /*
+ * Clear ioctl data buffer in case it's bigger than
+ * bitmap size
+ */
+ bzero(data, len);
+
+ limit = bitstr_size(limit);
+ len = MIN(limit, len);
+ memcpy(data, bitmap, len);
+ return (0);
+}
+
+void
+evdev_revoke_client(struct evdev_client *client)
+{
+
+ EVDEV_LOCK_ASSERT(client->ec_evdev);
+
+ client->ec_revoked = true;
+}
+
+void
+evdev_notify_event(struct evdev_client *client)
+{
+
+ EVDEV_CLIENT_LOCKQ_ASSERT(client);
+
+ if (client->ec_blocked) {
+ client->ec_blocked = false;
+ wakeup(client);
+ }
+ if (client->ec_selected) {
+ client->ec_selected = false;
+ selwakeup(&client->ec_selp);
+ }
+ KNOTE_LOCKED(&client->ec_selp.si_note, 0);
+
+ if (client->ec_async && client->ec_sigio != NULL)
+ pgsigio(&client->ec_sigio, SIGIO, 0);
+}
+
+int
+evdev_cdev_create(struct evdev_dev *evdev)
+{
+ struct make_dev_args mda;
+ int ret, unit = 0;
+
+ make_dev_args_init(&mda);
+ mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
+ mda.mda_devsw = &evdev_cdevsw;
+ mda.mda_uid = UID_ROOT;
+ mda.mda_gid = GID_WHEEL;
+ mda.mda_mode = 0600;
+ mda.mda_si_drv1 = evdev;
+
+ /* Try to coexist with cuse-backed input/event devices */
+ while ((ret = make_dev_s(&mda, &evdev->ev_cdev, "input/event%d", unit))
+ == EEXIST)
+ unit++;
+
+ if (ret == 0)
+ evdev->ev_unit = unit;
+
+ return (ret);
+}
+
+int
+evdev_cdev_destroy(struct evdev_dev *evdev)
+{
+
+ destroy_dev(evdev->ev_cdev);
+ return (0);
+}
+
+static void
+evdev_client_gettime(struct evdev_client *client, struct timeval *tv)
+{
+
+ switch (client->ec_clock_id) {
+ case EV_CLOCK_BOOTTIME:
+ /*
+ * XXX: FreeBSD does not support true POSIX monotonic clock.
+ * So aliase EV_CLOCK_BOOTTIME to EV_CLOCK_MONOTONIC.
+ */
+ case EV_CLOCK_MONOTONIC:
+ microuptime(tv);
+ break;
+
+ case EV_CLOCK_REALTIME:
+ default:
+ microtime(tv);
+ break;
+ }
+}
+
+void
+evdev_client_push(struct evdev_client *client, uint16_t type, uint16_t code,
+ int32_t value)
+{
+ struct timeval time;
+ size_t count, head, tail, ready;
+
+ EVDEV_CLIENT_LOCKQ_ASSERT(client);
+ head = client->ec_buffer_head;
+ tail = client->ec_buffer_tail;
+ ready = client->ec_buffer_ready;
+ count = client->ec_buffer_size;
+
+ /* If queue is full drop its content and place SYN_DROPPED event */
+ if ((tail + 1) % count == head) {
+ debugf(client, "client %p: buffer overflow", client);
+
+ head = (tail + count - 1) % count;
+ client->ec_buffer[head] = (struct input_event) {
+ .type = EV_SYN,
+ .code = SYN_DROPPED,
+ .value = 0
+ };
+ /*
+ * XXX: Here is a small race window from now till the end of
+ * report. The queue is empty but client has been already
+ * notified of data readyness. Can be fixed in two ways:
+ * 1. Implement bulk insert so queue lock would not be dropped
+ * till the SYN_REPORT event.
+ * 2. Insert SYN_REPORT just now and skip remaining events
+ */
+ client->ec_buffer_head = head;
+ client->ec_buffer_ready = head;
+ }
+
+ client->ec_buffer[tail].type = type;
+ client->ec_buffer[tail].code = code;
+ client->ec_buffer[tail].value = value;
+ client->ec_buffer_tail = (tail + 1) % count;
+
+ /* Allow users to read events only after report has been completed */
+ if (type == EV_SYN && code == SYN_REPORT) {
+ evdev_client_gettime(client, &time);
+ for (; ready != client->ec_buffer_tail;
+ ready = (ready + 1) % count)
+ client->ec_buffer[ready].time = time;
+ client->ec_buffer_ready = client->ec_buffer_tail;
+ }
+}
+
+void
+evdev_client_dumpqueue(struct evdev_client *client)
+{
+ struct input_event *event;
+ size_t i, head, tail, ready, size;
+
+ head = client->ec_buffer_head;
+ tail = client->ec_buffer_tail;
+ ready = client->ec_buffer_ready;
+ size = client->ec_buffer_size;
+
+ printf("evdev client: %p\n", client);
+ printf("event queue: head=%zu ready=%zu tail=%zu size=%zu\n",
+ head, ready, tail, size);
+
+ printf("queue contents:\n");
+
+ for (i = 0; i < size; i++) {
+ event = &client->ec_buffer[i];
+ printf("%zu: ", i);
+
+ if (i < head || i > tail)
+ printf("unused\n");
+ else
+ printf("type=%d code=%d value=%d ", event->type,
+ event->code, event->value);
+
+ if (i == head)
+ printf("<- head\n");
+ else if (i == tail)
+ printf("<- tail\n");
+ else if (i == ready)
+ printf("<- ready\n");
+ else
+ printf("\n");
+ }
+}
+
+static void
+evdev_client_filter_queue(struct evdev_client *client, uint16_t type)
+{
+ struct input_event *event;
+ size_t head, tail, count, i;
+ bool last_was_syn = false;
+
+ EVDEV_CLIENT_LOCKQ(client);
+
+ i = head = client->ec_buffer_head;
+ tail = client->ec_buffer_tail;
+ count = client->ec_buffer_size;
+ client->ec_buffer_ready = client->ec_buffer_tail;
+
+ while (i != client->ec_buffer_tail) {
+ event = &client->ec_buffer[i];
+ i = (i + 1) % count;
+
+ /* Skip event of given type */
+ if (event->type == type)
+ continue;
+
+ /* Remove empty SYN_REPORT events */
+ if (event->type == EV_SYN && event->code == SYN_REPORT) {
+ if (last_was_syn)
+ continue;
+ else
+ client->ec_buffer_ready = (tail + 1) % count;
+ }
+
+ /* Rewrite entry */
+ memcpy(&client->ec_buffer[tail], event,
+ sizeof(struct input_event));
+
+ last_was_syn = (event->type == EV_SYN &&
+ event->code == SYN_REPORT);
+
+ tail = (tail + 1) % count;
+ }
+
+ client->ec_buffer_head = i;
+ client->ec_buffer_tail = tail;
+
+ EVDEV_CLIENT_UNLOCKQ(client);
+}
diff --git a/sys/dev/evdev/evdev.c b/sys/dev/evdev/evdev.c
new file mode 100644
index 0000000..63e0496
--- /dev/null
+++ b/sys/dev/evdev/evdev.c
@@ -0,0 +1,949 @@
+/*-
+ * Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
+ * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
+ * 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$
+ */
+
+#include "opt_evdev.h"
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/bitstring.h>
+#include <sys/sysctl.h>
+
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/evdev_private.h>
+
+#ifdef EVDEV_DEBUG
+#define debugf(evdev, fmt, args...) printf("evdev: " fmt "\n", ##args)
+#else
+#define debugf(evdev, fmt, args...)
+#endif
+
+#ifdef FEATURE
+FEATURE(evdev, "Input event devices support");
+#endif
+
+enum evdev_sparse_result
+{
+ EV_SKIP_EVENT, /* Event value not changed */
+ EV_REPORT_EVENT, /* Event value changed */
+ EV_REPORT_MT_SLOT, /* Event value and MT slot number changed */
+};
+
+MALLOC_DEFINE(M_EVDEV, "evdev", "evdev memory");
+
+int evdev_rcpt_mask = EVDEV_RCPT_SYSMOUSE | EVDEV_RCPT_KBDMUX;
+
+SYSCTL_NODE(_kern, OID_AUTO, evdev, CTLFLAG_RW, 0, "Evdev args");
+SYSCTL_INT(_kern_evdev, OID_AUTO, rcpt_mask, CTLFLAG_RW, &evdev_rcpt_mask, 0,
+ "Who is receiving events: bit0 - sysmouse, bit1 - kbdmux, "
+ "bit2 - mouse hardware, bit3 - keyboard hardware");
+
+static void evdev_start_repeat(struct evdev_dev *, uint16_t);
+static void evdev_stop_repeat(struct evdev_dev *);
+static int evdev_check_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
+
+static inline void
+bit_change(bitstr_t *bitstr, int bit, int value)
+{
+ if (value)
+ bit_set(bitstr, bit);
+ else
+ bit_clear(bitstr, bit);
+}
+
+struct evdev_dev *
+evdev_alloc(void)
+{
+
+ return malloc(sizeof(struct evdev_dev), M_EVDEV, M_WAITOK | M_ZERO);
+}
+
+void
+evdev_free(struct evdev_dev *evdev)
+{
+
+ if (evdev != NULL && evdev->ev_cdev != NULL &&
+ evdev->ev_cdev->si_drv1 != NULL)
+ evdev_unregister(evdev);
+
+ free(evdev, M_EVDEV);
+}
+
+static struct input_absinfo *
+evdev_alloc_absinfo(void)
+{
+
+ return (malloc(sizeof(struct input_absinfo) * ABS_CNT, M_EVDEV,
+ M_WAITOK | M_ZERO));
+}
+
+static void
+evdev_free_absinfo(struct input_absinfo *absinfo)
+{
+
+ free(absinfo, M_EVDEV);
+}
+
+int
+evdev_set_report_size(struct evdev_dev *evdev, size_t report_size)
+{
+ if (report_size > KEY_CNT + REL_CNT + ABS_CNT + MAX_MT_SLOTS * MT_CNT +
+ MSC_CNT + LED_CNT + SND_CNT + SW_CNT + FF_CNT)
+ return (EINVAL);
+
+ evdev->ev_report_size = report_size;
+ return (0);
+}
+
+static size_t
+evdev_estimate_report_size(struct evdev_dev *evdev)
+{
+ size_t size = 0;
+ int res;
+
+ /*
+ * Keyboards generate one event per report but other devices with
+ * buttons like mouses can report events simultaneously
+ */
+ bit_ffs_at(evdev->ev_key_flags, KEY_OK, KEY_CNT - KEY_OK, &res);
+ if (res == -1)
+ bit_ffs(evdev->ev_key_flags, BTN_MISC, &res);
+ size += (res != -1);
+ bit_count(evdev->ev_key_flags, BTN_MISC, KEY_OK - BTN_MISC, &res);
+ size += res;
+
+ /* All relative axes can be reported simultaneously */
+ bit_count(evdev->ev_rel_flags, 0, REL_CNT, &res);
+ size += res;
+
+ /*
+ * All absolute axes can be reported simultaneously.
+ * Multitouch axes can be reported ABS_MT_SLOT times
+ */
+ if (evdev->ev_absinfo != NULL) {
+ bit_count(evdev->ev_abs_flags, 0, ABS_CNT, &res);
+ size += res;
+ bit_count(evdev->ev_abs_flags, ABS_MT_FIRST, MT_CNT, &res);
+ if (res > 0) {
+ res++; /* ABS_MT_SLOT or SYN_MT_REPORT */
+ if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
+ /* MT type B */
+ size += res * MAXIMAL_MT_SLOT(evdev);
+ else
+ /* MT type A */
+ size += res * (MAX_MT_REPORTS - 1);
+ }
+ }
+
+ /* All misc events can be reported simultaneously */
+ bit_count(evdev->ev_msc_flags, 0, MSC_CNT, &res);
+ size += res;
+
+ /* All leds can be reported simultaneously */
+ bit_count(evdev->ev_led_flags, 0, LED_CNT, &res);
+ size += res;
+
+ /* Assume other events are generated once per report */
+ bit_ffs(evdev->ev_snd_flags, SND_CNT, &res);
+ size += (res != -1);
+
+ bit_ffs(evdev->ev_sw_flags, SW_CNT, &res);
+ size += (res != -1);
+
+ /* XXX: FF part is not implemented yet */
+
+ size++; /* SYN_REPORT */
+ return (size);
+}
+
+static int
+evdev_register_common(struct evdev_dev *evdev)
+{
+ int ret;
+
+ debugf(evdev, "%s: registered evdev provider: %s <%s>\n",
+ evdev->ev_shortname, evdev->ev_name, evdev->ev_serial);
+
+ /* Initialize internal structures */
+ LIST_INIT(&evdev->ev_clients);
+
+ if (evdev_event_supported(evdev, EV_REP) &&
+ bit_test(evdev->ev_flags, EVDEV_FLAG_SOFTREPEAT)) {
+ /* Initialize callout */
+ callout_init_mtx(&evdev->ev_rep_callout, &evdev->ev_mtx, 0);
+
+ if (evdev->ev_rep[REP_DELAY] == 0 &&
+ evdev->ev_rep[REP_PERIOD] == 0) {
+ /* Supply default values */
+ evdev->ev_rep[REP_DELAY] = 250;
+ evdev->ev_rep[REP_PERIOD] = 33;
+ }
+ }
+
+ /* Initialize multitouch protocol type B states */
+ if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT) &&
+ evdev->ev_absinfo != NULL && MAXIMAL_MT_SLOT(evdev) > 0)
+ evdev_mt_init(evdev);
+
+ /* Estimate maximum report size */
+ if (evdev->ev_report_size == 0) {
+ ret = evdev_set_report_size(evdev,
+ evdev_estimate_report_size(evdev));
+ if (ret != 0)
+ goto bail_out;
+ }
+
+ /* Create char device node */
+ ret = evdev_cdev_create(evdev);
+bail_out:
+ return (ret);
+}
+
+int
+evdev_register(struct evdev_dev *evdev)
+{
+ int ret;
+
+ evdev->ev_lock_type = EV_LOCK_INTERNAL;
+ evdev->ev_lock = &evdev->ev_mtx;
+ mtx_init(&evdev->ev_mtx, "evmtx", NULL, MTX_DEF);
+
+ ret = evdev_register_common(evdev);
+ if (ret != 0)
+ mtx_destroy(&evdev->ev_mtx);
+
+ return (ret);
+}
+
+int
+evdev_register_mtx(struct evdev_dev *evdev, struct mtx *mtx)
+{
+
+ evdev->ev_lock_type = EV_LOCK_MTX;
+ evdev->ev_lock = mtx;
+ return (evdev_register_common(evdev));
+}
+
+int
+evdev_unregister(struct evdev_dev *evdev)
+{
+ struct evdev_client *client;
+ int ret;
+ debugf(evdev, "%s: unregistered evdev provider: %s\n",
+ evdev->ev_shortname, evdev->ev_name);
+
+ EVDEV_LOCK(evdev);
+ evdev->ev_cdev->si_drv1 = NULL;
+ /* Wake up sleepers */
+ LIST_FOREACH(client, &evdev->ev_clients, ec_link) {
+ evdev_revoke_client(client);
+ evdev_dispose_client(evdev, client);
+ EVDEV_CLIENT_LOCKQ(client);
+ evdev_notify_event(client);
+ EVDEV_CLIENT_UNLOCKQ(client);
+ }
+ EVDEV_UNLOCK(evdev);
+
+ /* destroy_dev can sleep so release lock */
+ ret = evdev_cdev_destroy(evdev);
+ evdev->ev_cdev = NULL;
+ if (ret == 0 && evdev->ev_lock_type == EV_LOCK_INTERNAL)
+ mtx_destroy(&evdev->ev_mtx);
+
+ evdev_free_absinfo(evdev->ev_absinfo);
+ evdev_mt_free(evdev);
+
+ return (ret);
+}
+
+inline void
+evdev_set_name(struct evdev_dev *evdev, const char *name)
+{
+
+ snprintf(evdev->ev_name, NAMELEN, "%s", name);
+}
+
+inline void
+evdev_set_id(struct evdev_dev *evdev, uint16_t bustype, uint16_t vendor,
+ uint16_t product, uint16_t version)
+{
+
+ evdev->ev_id = (struct input_id) {
+ .bustype = bustype,
+ .vendor = vendor,
+ .product = product,
+ .version = version
+ };
+}
+
+inline void
+evdev_set_phys(struct evdev_dev *evdev, const char *name)
+{
+
+ snprintf(evdev->ev_shortname, NAMELEN, "%s", name);
+}
+
+inline void
+evdev_set_serial(struct evdev_dev *evdev, const char *serial)
+{
+
+ snprintf(evdev->ev_serial, NAMELEN, "%s", serial);
+}
+
+inline void
+evdev_set_methods(struct evdev_dev *evdev, void *softc,
+ const struct evdev_methods *methods)
+{
+
+ evdev->ev_methods = methods;
+ evdev->ev_softc = softc;
+}
+
+inline void
+evdev_support_prop(struct evdev_dev *evdev, uint16_t prop)
+{
+
+ KASSERT(prop < INPUT_PROP_CNT, ("invalid evdev input property"));
+ bit_set(evdev->ev_prop_flags, prop);
+}
+
+inline void
+evdev_support_event(struct evdev_dev *evdev, uint16_t type)
+{
+
+ KASSERT(type < EV_CNT, ("invalid evdev event property"));
+ bit_set(evdev->ev_type_flags, type);
+}
+
+inline void
+evdev_support_key(struct evdev_dev *evdev, uint16_t code)
+{
+
+ KASSERT(code < KEY_CNT, ("invalid evdev key property"));
+ bit_set(evdev->ev_key_flags, code);
+}
+
+inline void
+evdev_support_rel(struct evdev_dev *evdev, uint16_t code)
+{
+
+ KASSERT(code < REL_CNT, ("invalid evdev rel property"));
+ bit_set(evdev->ev_rel_flags, code);
+}
+
+inline void
+evdev_support_abs(struct evdev_dev *evdev, uint16_t code, int32_t value,
+ int32_t minimum, int32_t maximum, int32_t fuzz, int32_t flat,
+ int32_t resolution)
+{
+ struct input_absinfo absinfo;
+
+ KASSERT(code < ABS_CNT, ("invalid evdev abs property"));
+
+ absinfo = (struct input_absinfo) {
+ .value = value,
+ .minimum = minimum,
+ .maximum = maximum,
+ .fuzz = fuzz,
+ .flat = flat,
+ .resolution = resolution,
+ };
+ evdev_set_abs_bit(evdev, code);
+ evdev_set_absinfo(evdev, code, &absinfo);
+}
+
+inline void
+evdev_set_abs_bit(struct evdev_dev *evdev, uint16_t code)
+{
+
+ KASSERT(code < ABS_CNT, ("invalid evdev abs property"));
+ if (evdev->ev_absinfo == NULL)
+ evdev->ev_absinfo = evdev_alloc_absinfo();
+ bit_set(evdev->ev_abs_flags, code);
+}
+
+inline void
+evdev_support_msc(struct evdev_dev *evdev, uint16_t code)
+{
+
+ KASSERT(code < MSC_CNT, ("invalid evdev msc property"));
+ bit_set(evdev->ev_msc_flags, code);
+}
+
+
+inline void
+evdev_support_led(struct evdev_dev *evdev, uint16_t code)
+{
+
+ KASSERT(code < LED_CNT, ("invalid evdev led property"));
+ bit_set(evdev->ev_led_flags, code);
+}
+
+inline void
+evdev_support_snd(struct evdev_dev *evdev, uint16_t code)
+{
+
+ KASSERT(code < SND_CNT, ("invalid evdev snd property"));
+ bit_set(evdev->ev_snd_flags, code);
+}
+
+inline void
+evdev_support_sw(struct evdev_dev *evdev, uint16_t code)
+{
+
+ KASSERT(code < SW_CNT, ("invalid evdev sw property"));
+ bit_set(evdev->ev_sw_flags, code);
+}
+
+bool
+evdev_event_supported(struct evdev_dev *evdev, uint16_t type)
+{
+
+ KASSERT(type < EV_CNT, ("invalid evdev event property"));
+ return (bit_test(evdev->ev_type_flags, type));
+}
+
+inline void
+evdev_set_absinfo(struct evdev_dev *evdev, uint16_t axis,
+ struct input_absinfo *absinfo)
+{
+
+ KASSERT(axis < ABS_CNT, ("invalid evdev abs property"));
+
+ if (axis == ABS_MT_SLOT &&
+ (absinfo->maximum < 1 || absinfo->maximum >= MAX_MT_SLOTS))
+ return;
+
+ if (evdev->ev_absinfo == NULL)
+ evdev->ev_absinfo = evdev_alloc_absinfo();
+
+ if (axis == ABS_MT_SLOT)
+ evdev->ev_absinfo[ABS_MT_SLOT].maximum = absinfo->maximum;
+ else
+ memcpy(&evdev->ev_absinfo[axis], absinfo,
+ sizeof(struct input_absinfo));
+}
+
+inline void
+evdev_set_repeat_params(struct evdev_dev *evdev, uint16_t property, int value)
+{
+
+ KASSERT(property < REP_CNT, ("invalid evdev repeat property"));
+ evdev->ev_rep[property] = value;
+}
+
+inline void
+evdev_set_flag(struct evdev_dev *evdev, uint16_t flag)
+{
+
+ KASSERT(flag < EVDEV_FLAG_CNT, ("invalid evdev flag property"));
+ bit_set(evdev->ev_flags, flag);
+}
+
+static int
+evdev_check_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
+ int32_t value)
+{
+
+ if (type >= EV_CNT)
+ return (EINVAL);
+
+ /* Allow SYN events implicitly */
+ if (type != EV_SYN && !evdev_event_supported(evdev, type))
+ return (EINVAL);
+
+ switch (type) {
+ case EV_SYN:
+ if (code >= SYN_CNT)
+ return (EINVAL);
+ break;
+
+ case EV_KEY:
+ if (code >= KEY_CNT)
+ return (EINVAL);
+ if (!bit_test(evdev->ev_key_flags, code))
+ return (EINVAL);
+ break;
+
+ case EV_REL:
+ if (code >= REL_CNT)
+ return (EINVAL);
+ if (!bit_test(evdev->ev_rel_flags, code))
+ return (EINVAL);
+ break;
+
+ case EV_ABS:
+ if (code >= ABS_CNT)
+ return (EINVAL);
+ if (!bit_test(evdev->ev_abs_flags, code))
+ return (EINVAL);
+ if (code == ABS_MT_SLOT &&
+ (value < 0 || value > MAXIMAL_MT_SLOT(evdev)))
+ return (EINVAL);
+ if (ABS_IS_MT(code) && evdev->ev_mt == NULL &&
+ bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
+ return (EINVAL);
+ break;
+
+ case EV_MSC:
+ if (code >= MSC_CNT)
+ return (EINVAL);
+ if (!bit_test(evdev->ev_msc_flags, code))
+ return (EINVAL);
+ break;
+
+ case EV_LED:
+ if (code >= LED_CNT)
+ return (EINVAL);
+ if (!bit_test(evdev->ev_led_flags, code))
+ return (EINVAL);
+ break;
+
+ case EV_SND:
+ if (code >= SND_CNT)
+ return (EINVAL);
+ if (!bit_test(evdev->ev_snd_flags, code))
+ return (EINVAL);
+ break;
+
+ case EV_SW:
+ if (code >= SW_CNT)
+ return (EINVAL);
+ if (!bit_test(evdev->ev_sw_flags, code))
+ return (EINVAL);
+ break;
+
+ case EV_REP:
+ if (code >= REP_CNT)
+ return (EINVAL);
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static void
+evdev_modify_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
+ int32_t *value)
+{
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ switch (type) {
+ case EV_KEY:
+ if (!evdev_event_supported(evdev, EV_REP))
+ break;
+
+ if (!bit_test(evdev->ev_flags, EVDEV_FLAG_SOFTREPEAT)) {
+ /* Detect driver key repeats. */
+ if (bit_test(evdev->ev_key_states, code) &&
+ *value == KEY_EVENT_DOWN)
+ *value = KEY_EVENT_REPEAT;
+ } else {
+ /* Start/stop callout for evdev repeats */
+ if (bit_test(evdev->ev_key_states, code) == !*value) {
+ if (*value == KEY_EVENT_DOWN)
+ evdev_start_repeat(evdev, code);
+ else
+ evdev_stop_repeat(evdev);
+ }
+ }
+ break;
+
+ case EV_ABS:
+ /* TBD: implement fuzz */
+ break;
+ }
+}
+
+static enum evdev_sparse_result
+evdev_sparse_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
+ int32_t value)
+{
+ int32_t last_mt_slot;
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ /*
+ * For certain event types, update device state bits
+ * and convert level reporting to edge reporting
+ */
+ switch (type) {
+ case EV_KEY:
+ switch (value) {
+ case KEY_EVENT_UP:
+ case KEY_EVENT_DOWN:
+ if (bit_test(evdev->ev_key_states, code) == value)
+ return (EV_SKIP_EVENT);
+ bit_change(evdev->ev_key_states, code, value);
+ break;
+
+ case KEY_EVENT_REPEAT:
+ if (bit_test(evdev->ev_key_states, code) == 0 ||
+ !evdev_event_supported(evdev, EV_REP))
+ return (EV_SKIP_EVENT);
+ break;
+
+ default:
+ return (EV_SKIP_EVENT);
+ }
+ break;
+
+ case EV_LED:
+ if (bit_test(evdev->ev_led_states, code) == value)
+ return (EV_SKIP_EVENT);
+ bit_change(evdev->ev_led_states, code, value);
+ break;
+
+ case EV_SND:
+ if (bit_test(evdev->ev_snd_states, code) == value)
+ return (EV_SKIP_EVENT);
+ bit_change(evdev->ev_snd_states, code, value);
+ break;
+
+ case EV_SW:
+ if (bit_test(evdev->ev_sw_states, code) == value)
+ return (EV_SKIP_EVENT);
+ bit_change(evdev->ev_sw_states, code, value);
+ break;
+
+ case EV_REP:
+ if (evdev->ev_rep[code] == value)
+ return (EV_SKIP_EVENT);
+ evdev_set_repeat_params(evdev, code, value);
+ break;
+
+ case EV_REL:
+ if (value == 0)
+ return (EV_SKIP_EVENT);
+ break;
+
+ /* For EV_ABS, save last value in absinfo and ev_mt_states */
+ case EV_ABS:
+ switch (code) {
+ case ABS_MT_SLOT:
+ /* Postpone ABS_MT_SLOT till next event */
+ evdev_set_last_mt_slot(evdev, value);
+ return (EV_SKIP_EVENT);
+
+ case ABS_MT_FIRST ... ABS_MT_LAST:
+ /* Pass MT protocol type A events as is */
+ if (!bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
+ break;
+ /* Don`t repeat MT protocol type B events */
+ last_mt_slot = evdev_get_last_mt_slot(evdev);
+ if (evdev_get_mt_value(evdev, last_mt_slot, code)
+ == value)
+ return (EV_SKIP_EVENT);
+ evdev_set_mt_value(evdev, last_mt_slot, code, value);
+ if (last_mt_slot != CURRENT_MT_SLOT(evdev)) {
+ CURRENT_MT_SLOT(evdev) = last_mt_slot;
+ evdev->ev_report_opened = true;
+ return (EV_REPORT_MT_SLOT);
+ }
+ break;
+
+ default:
+ if (evdev->ev_absinfo[code].value == value)
+ return (EV_SKIP_EVENT);
+ evdev->ev_absinfo[code].value = value;
+ }
+ break;
+
+ case EV_SYN:
+ if (code == SYN_REPORT) {
+ /* Count empty reports as well as non empty */
+ evdev->ev_report_count++;
+ /* Skip empty reports */
+ if (!evdev->ev_report_opened)
+ return (EV_SKIP_EVENT);
+ evdev->ev_report_opened = false;
+ return (EV_REPORT_EVENT);
+ }
+ break;
+ }
+
+ evdev->ev_report_opened = true;
+ return (EV_REPORT_EVENT);
+}
+
+static void
+evdev_propagate_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
+ int32_t value)
+{
+ struct evdev_client *client;
+
+ debugf(evdev, "%s pushed event %d/%d/%d",
+ evdev->ev_shortname, type, code, value);
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ /* Propagate event through all clients */
+ LIST_FOREACH(client, &evdev->ev_clients, ec_link) {
+ if (evdev->ev_grabber != NULL && evdev->ev_grabber != client)
+ continue;
+
+ EVDEV_CLIENT_LOCKQ(client);
+ evdev_client_push(client, type, code, value);
+ if (type == EV_SYN && code == SYN_REPORT)
+ evdev_notify_event(client);
+ EVDEV_CLIENT_UNLOCKQ(client);
+ }
+
+ evdev->ev_event_count++;
+}
+
+void
+evdev_send_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
+ int32_t value)
+{
+ enum evdev_sparse_result sparse;
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ sparse = evdev_sparse_event(evdev, type, code, value);
+ switch (sparse) {
+ case EV_REPORT_MT_SLOT:
+ /* report postponed ABS_MT_SLOT */
+ evdev_propagate_event(evdev, EV_ABS, ABS_MT_SLOT,
+ CURRENT_MT_SLOT(evdev));
+ /* FALLTHROUGH */
+ case EV_REPORT_EVENT:
+ evdev_propagate_event(evdev, type, code, value);
+ /* FALLTHROUGH */
+ case EV_SKIP_EVENT:
+ break;
+ }
+}
+
+int
+evdev_push_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
+ int32_t value)
+{
+
+ if (evdev->ev_lock_type != EV_LOCK_INTERNAL)
+ EVDEV_LOCK_ASSERT(evdev);
+
+ if (evdev_check_event(evdev, type, code, value) != 0)
+ return (EINVAL);
+
+ if (evdev->ev_lock_type == EV_LOCK_INTERNAL)
+ EVDEV_LOCK(evdev);
+ evdev_modify_event(evdev, type, code, &value);
+ if (type == EV_SYN && code == SYN_REPORT &&
+ bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL))
+ evdev_send_mt_autorel(evdev);
+ if (type == EV_SYN && code == SYN_REPORT && evdev->ev_report_opened &&
+ bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
+ evdev_send_mt_compat(evdev);
+ evdev_send_event(evdev, type, code, value);
+ if (evdev->ev_lock_type == EV_LOCK_INTERNAL)
+ EVDEV_UNLOCK(evdev);
+
+ return (0);
+}
+
+int
+evdev_inject_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
+ int32_t value)
+{
+ int ret = 0;
+
+ switch (type) {
+ case EV_REP:
+ /* evdev repeats should not be processed by hardware driver */
+ if (bit_test(evdev->ev_flags, EVDEV_FLAG_SOFTREPEAT))
+ goto push;
+ /* FALLTHROUGH */
+ case EV_LED:
+ case EV_MSC:
+ case EV_SND:
+ case EV_FF:
+ if (evdev->ev_methods != NULL &&
+ evdev->ev_methods->ev_event != NULL)
+ evdev->ev_methods->ev_event(evdev, evdev->ev_softc,
+ type, code, value);
+ /*
+ * Leds and driver repeats should be reported in ev_event
+ * method body to interoperate with kbdmux states and rates
+ * propagation so both ways (ioctl and evdev) of changing it
+ * will produce only one evdev event report to client.
+ */
+ if (type == EV_LED || type == EV_REP)
+ break;
+ /* FALLTHROUGH */
+ case EV_SYN:
+ case EV_KEY:
+ case EV_REL:
+ case EV_ABS:
+ case EV_SW:
+push:
+ ret = evdev_push_event(evdev, type, code, value);
+ break;
+
+ default:
+ ret = EINVAL;
+ }
+
+ return (ret);
+}
+
+inline int
+evdev_sync(struct evdev_dev *evdev)
+{
+
+ return (evdev_push_event(evdev, EV_SYN, SYN_REPORT, 1));
+}
+
+
+inline int
+evdev_mt_sync(struct evdev_dev *evdev)
+{
+
+ return (evdev_push_event(evdev, EV_SYN, SYN_MT_REPORT, 1));
+}
+
+int
+evdev_register_client(struct evdev_dev *evdev, struct evdev_client *client)
+{
+ int ret = 0;
+
+ debugf(evdev, "adding new client for device %s", evdev->ev_shortname);
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ if (LIST_EMPTY(&evdev->ev_clients) && evdev->ev_methods != NULL &&
+ evdev->ev_methods->ev_open != NULL) {
+ debugf(evdev, "calling ev_open() on device %s",
+ evdev->ev_shortname);
+ ret = evdev->ev_methods->ev_open(evdev, evdev->ev_softc);
+ }
+ if (ret == 0)
+ LIST_INSERT_HEAD(&evdev->ev_clients, client, ec_link);
+ return (ret);
+}
+
+void
+evdev_dispose_client(struct evdev_dev *evdev, struct evdev_client *client)
+{
+ debugf(evdev, "removing client for device %s", evdev->ev_shortname);
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ LIST_REMOVE(client, ec_link);
+ if (LIST_EMPTY(&evdev->ev_clients)) {
+ if (evdev->ev_methods != NULL &&
+ evdev->ev_methods->ev_close != NULL)
+ evdev->ev_methods->ev_close(evdev, evdev->ev_softc);
+ if (evdev_event_supported(evdev, EV_REP) &&
+ bit_test(evdev->ev_flags, EVDEV_FLAG_SOFTREPEAT))
+ evdev_stop_repeat(evdev);
+ }
+ evdev_release_client(evdev, client);
+}
+
+int
+evdev_grab_client(struct evdev_dev *evdev, struct evdev_client *client)
+{
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ if (evdev->ev_grabber != NULL)
+ return (EBUSY);
+
+ evdev->ev_grabber = client;
+
+ return (0);
+}
+
+int
+evdev_release_client(struct evdev_dev *evdev, struct evdev_client *client)
+{
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ if (evdev->ev_grabber != client)
+ return (EINVAL);
+
+ evdev->ev_grabber = NULL;
+
+ return (0);
+}
+
+static void
+evdev_repeat_callout(void *arg)
+{
+ struct evdev_dev *evdev = (struct evdev_dev *)arg;
+
+ evdev_send_event(evdev, EV_KEY, evdev->ev_rep_key, KEY_EVENT_REPEAT);
+ evdev_send_event(evdev, EV_SYN, SYN_REPORT, 1);
+
+ if (evdev->ev_rep[REP_PERIOD])
+ callout_reset(&evdev->ev_rep_callout,
+ evdev->ev_rep[REP_PERIOD] * hz / 1000,
+ evdev_repeat_callout, evdev);
+ else
+ evdev->ev_rep_key = KEY_RESERVED;
+}
+
+static void
+evdev_start_repeat(struct evdev_dev *evdev, uint16_t key)
+{
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ if (evdev->ev_rep[REP_DELAY]) {
+ evdev->ev_rep_key = key;
+ callout_reset(&evdev->ev_rep_callout,
+ evdev->ev_rep[REP_DELAY] * hz / 1000,
+ evdev_repeat_callout, evdev);
+ }
+}
+
+static void
+evdev_stop_repeat(struct evdev_dev *evdev)
+{
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ if (evdev->ev_rep_key != KEY_RESERVED) {
+ callout_stop(&evdev->ev_rep_callout);
+ evdev->ev_rep_key = KEY_RESERVED;
+ }
+}
+
+MODULE_VERSION(evdev, 1);
diff --git a/sys/dev/evdev/evdev.h b/sys/dev/evdev/evdev.h
new file mode 100644
index 0000000..7287e73
--- /dev/null
+++ b/sys/dev/evdev/evdev.h
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 2014 Jakub Wojciech Klama <jceel@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 _DEV_EVDEV_EVDEV_H
+#define _DEV_EVDEV_EVDEV_H
+
+#include <sys/types.h>
+#include <sys/kbio.h>
+#include <dev/evdev/input.h>
+#include <dev/kbd/kbdreg.h>
+
+#define NAMELEN 80
+
+struct evdev_dev;
+
+typedef int (evdev_open_t)(struct evdev_dev *, void *);
+typedef void (evdev_close_t)(struct evdev_dev *, void *);
+typedef void (evdev_event_t)(struct evdev_dev *, void *, uint16_t,
+ uint16_t, int32_t);
+typedef void (evdev_keycode_t)(struct evdev_dev *, void *,
+ struct input_keymap_entry *);
+
+/*
+ * Keyboard and mouse events recipient mask.
+ * evdev_rcpt_mask variable should be respected by keyboard and mouse drivers
+ * that are able to send events through both evdev and sysmouse/kbdmux
+ * interfaces so user can choose prefered one to not receive one event twice.
+ */
+#define EVDEV_RCPT_SYSMOUSE (1<<0)
+#define EVDEV_RCPT_KBDMUX (1<<1)
+#define EVDEV_RCPT_HW_MOUSE (1<<2)
+#define EVDEV_RCPT_HW_KBD (1<<3)
+extern int evdev_rcpt_mask;
+
+#define ABS_MT_FIRST ABS_MT_TOUCH_MAJOR
+#define ABS_MT_LAST ABS_MT_TOOL_Y
+#define ABS_IS_MT(x) ((x) >= ABS_MT_FIRST && (x) <= ABS_MT_LAST)
+#define ABS_MT_INDEX(x) ((x) - ABS_MT_FIRST)
+#define MT_CNT (ABS_MT_INDEX(ABS_MT_LAST) + 1)
+/* Multitouch protocol type A */
+#define MAX_MT_REPORTS 5
+/* Multitouch protocol type B interface */
+#define MAX_MT_SLOTS 16
+
+#define EVDEV_FLAG_SOFTREPEAT 0x00 /* use evdev to repeat keys */
+#define EVDEV_FLAG_MT_STCOMPAT 0x01 /* autogenerate ST-compatible events
+ * for MT protocol type B reports */
+#define EVDEV_FLAG_MT_AUTOREL 0x02 /* Autorelease MT-slots not listed in
+ * current MT protocol type B report */
+#define EVDEV_FLAG_MAX 0x1F
+#define EVDEV_FLAG_CNT (EVDEV_FLAG_MAX + 1)
+
+struct evdev_methods
+{
+ evdev_open_t *ev_open;
+ evdev_close_t *ev_close;
+ evdev_event_t *ev_event;
+ evdev_keycode_t *ev_get_keycode;
+ evdev_keycode_t *ev_set_keycode;
+};
+
+/* Input device interface: */
+struct evdev_dev *evdev_alloc(void);
+void evdev_free(struct evdev_dev *);
+void evdev_set_name(struct evdev_dev *, const char *);
+void evdev_set_id(struct evdev_dev *, uint16_t, uint16_t, uint16_t, uint16_t);
+void evdev_set_phys(struct evdev_dev *, const char *);
+void evdev_set_serial(struct evdev_dev *, const char *);
+void evdev_set_methods(struct evdev_dev *, void *,
+ const struct evdev_methods *);
+int evdev_register(struct evdev_dev *);
+int evdev_register_mtx(struct evdev_dev *, struct mtx *);
+int evdev_unregister(struct evdev_dev *);
+int evdev_push_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
+int evdev_sync(struct evdev_dev *);
+int evdev_mt_sync(struct evdev_dev *);
+void evdev_support_prop(struct evdev_dev *, uint16_t);
+void evdev_support_event(struct evdev_dev *, uint16_t);
+void evdev_support_key(struct evdev_dev *, uint16_t);
+void evdev_support_rel(struct evdev_dev *, uint16_t);
+void evdev_support_abs(struct evdev_dev *, uint16_t, int32_t, int32_t, int32_t,
+ int32_t, int32_t, int32_t);
+void evdev_support_msc(struct evdev_dev *, uint16_t);
+void evdev_support_led(struct evdev_dev *, uint16_t);
+void evdev_support_snd(struct evdev_dev *, uint16_t);
+void evdev_support_sw(struct evdev_dev *, uint16_t);
+void evdev_set_repeat_params(struct evdev_dev *, uint16_t, int);
+int evdev_set_report_size(struct evdev_dev *, size_t);
+void evdev_set_flag(struct evdev_dev *, uint16_t);
+
+/* Multitouch related functions: */
+int32_t evdev_get_mt_slot_by_tracking_id(struct evdev_dev *, int32_t);
+void evdev_support_nfingers(struct evdev_dev *, int32_t);
+void evdev_support_mt_compat(struct evdev_dev *);
+void evdev_push_nfingers(struct evdev_dev *, int32_t);
+void evdev_push_mt_compat(struct evdev_dev *);
+
+/* Utility functions: */
+uint16_t evdev_hid2key(int);
+void evdev_support_all_known_keys(struct evdev_dev *);
+uint16_t evdev_scancode2key(int *, int);
+void evdev_push_mouse_btn(struct evdev_dev *, int);
+void evdev_push_leds(struct evdev_dev *, int);
+void evdev_push_repeats(struct evdev_dev *, keyboard_t *);
+evdev_event_t evdev_ev_kbd_event;
+
+#endif /* _DEV_EVDEV_EVDEV_H */
diff --git a/sys/dev/evdev/evdev_mt.c b/sys/dev/evdev/evdev_mt.c
new file mode 100644
index 0000000..82f36d8
--- /dev/null
+++ b/sys/dev/evdev/evdev_mt.c
@@ -0,0 +1,292 @@
+/*-
+ * Copyright (c) 2016 Vladimir Kondratyev <wulf@cicgroup.ru>
+ * 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$
+ */
+
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/evdev_private.h>
+
+#ifdef DEBUG
+#define debugf(fmt, args...) printf("evdev: " fmt "\n", ##args)
+#else
+#define debugf(fmt, args...)
+#endif
+
+static uint16_t evdev_fngmap[] = {
+ BTN_TOOL_FINGER,
+ BTN_TOOL_DOUBLETAP,
+ BTN_TOOL_TRIPLETAP,
+ BTN_TOOL_QUADTAP,
+ BTN_TOOL_QUINTTAP,
+};
+
+static uint16_t evdev_mtstmap[][2] = {
+ { ABS_MT_POSITION_X, ABS_X },
+ { ABS_MT_POSITION_Y, ABS_Y },
+ { ABS_MT_PRESSURE, ABS_PRESSURE },
+ { ABS_MT_TOUCH_MAJOR, ABS_TOOL_WIDTH },
+};
+
+struct evdev_mt_slot {
+ uint64_t ev_report;
+ int32_t ev_mt_states[MT_CNT];
+};
+
+struct evdev_mt {
+ int32_t ev_mt_last_reported_slot;
+ struct evdev_mt_slot ev_mt_slots[];
+};
+
+void
+evdev_mt_init(struct evdev_dev *evdev)
+{
+ int32_t slot, slots;
+
+ slots = MAXIMAL_MT_SLOT(evdev) + 1;
+
+ evdev->ev_mt = malloc(offsetof(struct evdev_mt, ev_mt_slots) +
+ sizeof(struct evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO);
+
+ /* Initialize multitouch protocol type B states */
+ for (slot = 0; slot < slots; slot++) {
+ /*
+ * .ev_report should not be initialized to initial value of
+ * report counter (0) as it brokes free slot detection in
+ * evdev_get_mt_slot_by_tracking_id. So initialize it to -1
+ */
+ evdev->ev_mt->ev_mt_slots[slot] = (struct evdev_mt_slot) {
+ .ev_report = 0xFFFFFFFFFFFFFFFFULL,
+ .ev_mt_states[ABS_MT_INDEX(ABS_MT_TRACKING_ID)] = -1,
+ };
+ }
+
+ if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
+ evdev_support_mt_compat(evdev);
+}
+
+void
+evdev_mt_free(struct evdev_dev *evdev)
+{
+
+ free(evdev->ev_mt, M_EVDEV);
+}
+
+int32_t
+evdev_get_last_mt_slot(struct evdev_dev *evdev)
+{
+
+ return (evdev->ev_mt->ev_mt_last_reported_slot);
+}
+
+void
+evdev_set_last_mt_slot(struct evdev_dev *evdev, int32_t slot)
+{
+
+ evdev->ev_mt->ev_mt_slots[slot].ev_report = evdev->ev_report_count;
+ evdev->ev_mt->ev_mt_last_reported_slot = slot;
+}
+
+inline int32_t
+evdev_get_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code)
+{
+
+ return (evdev->ev_mt->
+ ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)]);
+}
+
+inline void
+evdev_set_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code,
+ int32_t value)
+{
+
+ evdev->ev_mt->ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)] =
+ value;
+}
+
+int32_t
+evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
+{
+ int32_t tr_id, slot, free_slot = -1;
+
+ for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
+ tr_id = evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID);
+ if (tr_id == tracking_id)
+ return (slot);
+ /*
+ * Its possible that slot will be reassigned in a place of just
+ * released one within the same report. To avoid this compare
+ * report counter with slot`s report number updated with each
+ * ABS_MT_TRACKING_ID change.
+ */
+ if (free_slot == -1 && tr_id == -1 &&
+ evdev->ev_mt->ev_mt_slots[slot].ev_report !=
+ evdev->ev_report_count)
+ free_slot = slot;
+ }
+
+ return (free_slot);
+}
+
+void
+evdev_support_nfingers(struct evdev_dev *evdev, int32_t nfingers)
+{
+ int32_t i;
+
+ for (i = 0; i < MIN(nitems(evdev_fngmap), nfingers); i++)
+ evdev_support_key(evdev, evdev_fngmap[i]);
+}
+
+void
+evdev_support_mt_compat(struct evdev_dev *evdev)
+{
+ int32_t i;
+
+ if (evdev->ev_absinfo == NULL)
+ return;
+
+ evdev_support_event(evdev, EV_KEY);
+ evdev_support_key(evdev, BTN_TOUCH);
+
+ /* Touchscreens should not advertise tap tool capabilities */
+ if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
+ evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
+
+ /* Echo 0-th MT-slot as ST-slot */
+ for (i = 0; i < nitems(evdev_mtstmap); i++)
+ if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][0]))
+ evdev_support_abs(evdev, evdev_mtstmap[i][1],
+ evdev->ev_absinfo[evdev_mtstmap[i][0]].value,
+ evdev->ev_absinfo[evdev_mtstmap[i][0]].minimum,
+ evdev->ev_absinfo[evdev_mtstmap[i][0]].maximum,
+ evdev->ev_absinfo[evdev_mtstmap[i][0]].fuzz,
+ evdev->ev_absinfo[evdev_mtstmap[i][0]].flat,
+ evdev->ev_absinfo[evdev_mtstmap[i][0]].resolution);
+}
+
+static int32_t
+evdev_count_fingers(struct evdev_dev *evdev)
+{
+ int32_t nfingers = 0, i;
+
+ for (i = 0; i <= MAXIMAL_MT_SLOT(evdev); i++)
+ if (evdev_get_mt_value(evdev, i, ABS_MT_TRACKING_ID) != -1)
+ nfingers++;
+
+ return (nfingers);
+}
+
+static void
+evdev_send_nfingers(struct evdev_dev *evdev, int32_t nfingers)
+{
+ int32_t i;
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ if (nfingers > nitems(evdev_fngmap))
+ nfingers = nitems(evdev_fngmap);
+
+ for (i = 0; i < nitems(evdev_fngmap); i++)
+ evdev_send_event(evdev, EV_KEY, evdev_fngmap[i],
+ nfingers == i + 1);
+}
+
+void
+evdev_push_nfingers(struct evdev_dev *evdev, int32_t nfingers)
+{
+
+ if (evdev->ev_lock_type == EV_LOCK_INTERNAL)
+ EVDEV_LOCK(evdev);
+ else
+ EVDEV_LOCK_ASSERT(evdev);
+ evdev_send_nfingers(evdev, nfingers);
+ if (evdev->ev_lock_type == EV_LOCK_INTERNAL)
+ EVDEV_UNLOCK(evdev);
+}
+
+void
+evdev_send_mt_compat(struct evdev_dev *evdev)
+{
+ int32_t nfingers, i;
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ nfingers = evdev_count_fingers(evdev);
+ evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
+
+ if (evdev_get_mt_value(evdev, 0, ABS_MT_TRACKING_ID) != -1)
+ /* Echo 0-th MT-slot as ST-slot */
+ for (i = 0; i < nitems(evdev_mtstmap); i++)
+ if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][1]))
+ evdev_send_event(evdev, EV_ABS,
+ evdev_mtstmap[i][1],
+ evdev_get_mt_value(evdev, 0,
+ evdev_mtstmap[i][0]));
+
+ /* Touchscreens should not report tool taps */
+ if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
+ evdev_send_nfingers(evdev, nfingers);
+
+ if (nfingers == 0)
+ evdev_send_event(evdev, EV_ABS, ABS_PRESSURE, 0);
+}
+
+void
+evdev_push_mt_compat(struct evdev_dev *evdev)
+{
+
+ if (evdev->ev_lock_type == EV_LOCK_INTERNAL)
+ EVDEV_LOCK(evdev);
+ else
+ EVDEV_LOCK_ASSERT(evdev);
+ evdev_send_mt_compat(evdev);
+ if (evdev->ev_lock_type == EV_LOCK_INTERNAL)
+ EVDEV_UNLOCK(evdev);
+}
+
+void
+evdev_send_mt_autorel(struct evdev_dev *evdev)
+{
+ int32_t slot;
+
+ EVDEV_LOCK_ASSERT(evdev);
+
+ for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
+ if (evdev->ev_mt->ev_mt_slots[slot].ev_report !=
+ evdev->ev_report_count &&
+ evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID) != -1){
+ evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
+ evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID,
+ -1);
+ }
+ }
+}
diff --git a/sys/dev/evdev/evdev_private.h b/sys/dev/evdev/evdev_private.h
new file mode 100644
index 0000000..b3de1bf
--- /dev/null
+++ b/sys/dev/evdev/evdev_private.h
@@ -0,0 +1,200 @@
+/*-
+ * Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
+ * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
+ * 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 _DEV_EVDEV_EVDEV_PRIVATE_H
+#define _DEV_EVDEV_EVDEV_PRIVATE_H
+
+#include <sys/bitstring.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/kbio.h>
+#include <sys/selinfo.h>
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/input.h>
+#include <dev/kbd/kbdreg.h>
+
+#define NAMELEN 80
+
+/*
+ * bitstr_t implementation must be identical to one found in EVIOCG*
+ * libevdev ioctls. Our bitstring(3) API is compatible since r299090.
+ */
+_Static_assert(sizeof(bitstr_t) == sizeof(unsigned long),
+ "bitstr_t size mismatch");
+
+MALLOC_DECLARE(M_EVDEV);
+
+struct evdev_client;
+struct evdev_mt;
+
+#define CURRENT_MT_SLOT(evdev) ((evdev)->ev_absinfo[ABS_MT_SLOT].value)
+#define MAXIMAL_MT_SLOT(evdev) ((evdev)->ev_absinfo[ABS_MT_SLOT].maximum)
+
+enum evdev_key_events
+{
+ KEY_EVENT_UP,
+ KEY_EVENT_DOWN,
+ KEY_EVENT_REPEAT
+};
+
+/* evdev clock IDs in Linux semantic */
+enum evdev_clock_id
+{
+ EV_CLOCK_REALTIME = 0, /* UTC clock */
+ EV_CLOCK_MONOTONIC, /* monotonic, stops on suspend */
+ EV_CLOCK_BOOTTIME /* monotonic, suspend-awared */
+};
+
+enum evdev_lock_type
+{
+ EV_LOCK_INTERNAL = 0, /* Internal evdev mutex */
+ EV_LOCK_MTX, /* Driver`s mutex */
+};
+
+struct evdev_dev
+{
+ char ev_name[NAMELEN];
+ char ev_shortname[NAMELEN];
+ char ev_serial[NAMELEN];
+ struct cdev * ev_cdev;
+ int ev_unit;
+ enum evdev_lock_type ev_lock_type;
+ struct mtx * ev_lock;
+ struct mtx ev_mtx;
+ struct input_id ev_id;
+ struct evdev_client * ev_grabber;
+ size_t ev_report_size;
+
+ /* Supported features: */
+ bitstr_t bit_decl(ev_prop_flags, INPUT_PROP_CNT);
+ bitstr_t bit_decl(ev_type_flags, EV_CNT);
+ bitstr_t bit_decl(ev_key_flags, KEY_CNT);
+ bitstr_t bit_decl(ev_rel_flags, REL_CNT);
+ bitstr_t bit_decl(ev_abs_flags, ABS_CNT);
+ bitstr_t bit_decl(ev_msc_flags, MSC_CNT);
+ bitstr_t bit_decl(ev_led_flags, LED_CNT);
+ bitstr_t bit_decl(ev_snd_flags, SND_CNT);
+ bitstr_t bit_decl(ev_sw_flags, SW_CNT);
+ struct input_absinfo * ev_absinfo;
+ bitstr_t bit_decl(ev_flags, EVDEV_FLAG_CNT);
+
+ /* Repeat parameters & callout: */
+ int ev_rep[REP_CNT];
+ struct callout ev_rep_callout;
+ uint16_t ev_rep_key;
+
+ /* State: */
+ bitstr_t bit_decl(ev_key_states, KEY_CNT);
+ bitstr_t bit_decl(ev_led_states, LED_CNT);
+ bitstr_t bit_decl(ev_snd_states, SND_CNT);
+ bitstr_t bit_decl(ev_sw_states, SW_CNT);
+ bool ev_report_opened;
+
+ /* Multitouch protocol type B state: */
+ struct evdev_mt * ev_mt;
+
+ /* Counters: */
+ uint64_t ev_event_count;
+ uint64_t ev_report_count;
+
+ /* Parent driver callbacks: */
+ const struct evdev_methods * ev_methods;
+ void * ev_softc;
+
+ LIST_ENTRY(evdev_dev) ev_link;
+ LIST_HEAD(, evdev_client) ev_clients;
+};
+
+#define EVDEV_LOCK(evdev) mtx_lock((evdev)->ev_lock)
+#define EVDEV_UNLOCK(evdev) mtx_unlock((evdev)->ev_lock)
+#define EVDEV_LOCK_ASSERT(evdev) mtx_assert((evdev)->ev_lock, MA_OWNED)
+
+struct evdev_client
+{
+ struct evdev_dev * ec_evdev;
+ struct mtx ec_buffer_mtx;
+ size_t ec_buffer_size;
+ size_t ec_buffer_head;
+ size_t ec_buffer_tail;
+ size_t ec_buffer_ready;
+ enum evdev_clock_id ec_clock_id;
+ struct selinfo ec_selp;
+ struct sigio * ec_sigio;
+ bool ec_async;
+ bool ec_revoked;
+ bool ec_blocked;
+ bool ec_selected;
+
+ LIST_ENTRY(evdev_client) ec_link;
+
+ struct input_event ec_buffer[];
+};
+
+#define EVDEV_CLIENT_LOCKQ(client) mtx_lock(&(client)->ec_buffer_mtx)
+#define EVDEV_CLIENT_UNLOCKQ(client) mtx_unlock(&(client)->ec_buffer_mtx)
+#define EVDEV_CLIENT_LOCKQ_ASSERT(client) \
+ mtx_assert(&(client)->ec_buffer_mtx, MA_OWNED)
+#define EVDEV_CLIENT_EMPTYQ(client) \
+ ((client)->ec_buffer_head == (client)->ec_buffer_ready)
+#define EVDEV_CLIENT_SIZEQ(client) \
+ (((client)->ec_buffer_ready + (client)->ec_buffer_size - \
+ (client)->ec_buffer_head) % (client)->ec_buffer_size)
+
+/* Input device interface: */
+void evdev_send_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
+int evdev_inject_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
+int evdev_cdev_create(struct evdev_dev *);
+int evdev_cdev_destroy(struct evdev_dev *);
+bool evdev_event_supported(struct evdev_dev *, uint16_t);
+void evdev_set_abs_bit(struct evdev_dev *, uint16_t);
+void evdev_set_absinfo(struct evdev_dev *, uint16_t, struct input_absinfo *);
+
+/* Client interface: */
+int evdev_register_client(struct evdev_dev *, struct evdev_client *);
+void evdev_dispose_client(struct evdev_dev *, struct evdev_client *);
+int evdev_grab_client(struct evdev_dev *, struct evdev_client *);
+int evdev_release_client(struct evdev_dev *, struct evdev_client *);
+void evdev_client_push(struct evdev_client *, uint16_t, uint16_t, int32_t);
+void evdev_notify_event(struct evdev_client *);
+void evdev_revoke_client(struct evdev_client *);
+
+/* Multitouch related functions: */
+void evdev_mt_init(struct evdev_dev *);
+void evdev_mt_free(struct evdev_dev *);
+int32_t evdev_get_last_mt_slot(struct evdev_dev *);
+void evdev_set_last_mt_slot(struct evdev_dev *, int32_t);
+int32_t evdev_get_mt_value(struct evdev_dev *, int32_t, int16_t);
+void evdev_set_mt_value(struct evdev_dev *, int32_t, int16_t, int32_t);
+void evdev_send_mt_compat(struct evdev_dev *);
+void evdev_send_mt_autorel(struct evdev_dev *);
+
+/* Utility functions: */
+void evdev_client_dumpqueue(struct evdev_client *);
+
+#endif /* _DEV_EVDEV_EVDEV_PRIVATE_H */
diff --git a/sys/dev/evdev/evdev_utils.c b/sys/dev/evdev/evdev_utils.c
new file mode 100644
index 0000000..47e5e64
--- /dev/null
+++ b/sys/dev/evdev/evdev_utils.c
@@ -0,0 +1,334 @@
+/*-
+ * Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
+ * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
+ * 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$
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/kbio.h>
+
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+
+#include <dev/kbd/kbdreg.h>
+
+#define NONE KEY_RESERVED
+
+static uint16_t evdev_usb_scancodes[256] = {
+ /* 0x00 - 0x27 */
+ NONE, NONE, NONE, NONE, KEY_A, KEY_B, KEY_C, KEY_D,
+ KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
+ KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
+ KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2,
+ KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0,
+ /* 0x28 - 0x3f */
+ KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB,
+ KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
+ KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON,
+ KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT,
+ KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2,
+ KEY_F3, KEY_F4, KEY_F5, KEY_F6,
+ /* 0x40 - 0x5f */
+ KEY_F7, KEY_F8, KEY_F9, KEY_F10,
+ KEY_F11, KEY_F12, KEY_SYSRQ, KEY_SCROLLLOCK,
+ KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP,
+ KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT,
+ KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUMLOCK,
+ KEY_SLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS,
+ KEY_KPENTER, KEY_KP1, KEY_KP2, KEY_KP3,
+ KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7,
+ /* 0x60 - 0x7f */
+ KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT,
+ KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL,
+ KEY_F13, KEY_F14, KEY_F15, KEY_F16,
+ KEY_F17, KEY_F18, KEY_F19, KEY_F20,
+ KEY_F21, KEY_F22, KEY_F23, KEY_F24,
+ KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT,
+ KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT,
+ KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE,
+ /* 0x80 - 0x9f */
+ KEY_VOLUMEUP, KEY_VOLUMEDOWN, NONE, NONE,
+ NONE, KEY_KPCOMMA, NONE, KEY_RO,
+ KEY_KATAKANAHIRAGANA, KEY_YEN,KEY_HENKAN, KEY_MUHENKAN,
+ KEY_KPJPCOMMA, NONE, NONE, NONE,
+ KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA,
+ KEY_ZENKAKUHANKAKU, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ /* 0xa0 - 0xbf */
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ /* 0xc0 - 0xdf */
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ /* 0xe0 - 0xff */
+ KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA,
+ KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA,
+ KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG,KEY_NEXTSONG,
+ KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE,
+ KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP,
+ KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT,
+ KEY_SLEEP, KEY_COFFEE, KEY_REFRESH, KEY_CALC,
+ NONE, NONE, NONE, NONE,
+
+};
+
+static uint16_t evdev_at_set1_scancodes[] = {
+ /* 0x00 - 0x1f */
+ NONE, KEY_ESC, KEY_1, KEY_2,
+ KEY_3, KEY_4, KEY_5, KEY_6,
+ KEY_7, KEY_8, KEY_9, KEY_0,
+ KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_TAB,
+ KEY_Q, KEY_W, KEY_E, KEY_R,
+ KEY_T, KEY_Y, KEY_U, KEY_I,
+ KEY_O, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE,
+ KEY_ENTER, KEY_LEFTCTRL, KEY_A, KEY_S,
+ /* 0x20 - 0x3f */
+ KEY_D, KEY_F, KEY_G, KEY_H,
+ KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,
+ KEY_APOSTROPHE, KEY_GRAVE, KEY_LEFTSHIFT, KEY_BACKSLASH,
+ KEY_Z, KEY_X, KEY_C, KEY_V,
+ KEY_B, KEY_N, KEY_M, KEY_COMMA,
+ KEY_DOT, KEY_SLASH, KEY_RIGHTSHIFT, NONE,
+ KEY_LEFTALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
+ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
+ /* 0x40 - 0x5f */
+ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
+ KEY_F10, KEY_NUMLOCK, KEY_SCROLLLOCK, KEY_KP7,
+ KEY_KP8, KEY_KP9, KEY_KPMINUS, KEY_KP4,
+ KEY_KP5, KEY_KP6, KEY_KPPLUS, KEY_KP1,
+ KEY_KP2, KEY_KP3, KEY_KP0, KEY_KPDOT,
+ NONE, NONE, NONE, KEY_F11,
+ KEY_F12, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ /* 0x60 - 0x7f */
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ KEY_KATAKANAHIRAGANA, NONE, NONE, KEY_RO,
+ NONE, NONE, KEY_ZENKAKUHANKAKU, KEY_HIRAGANA,
+ KEY_KATAKANA, KEY_HENKAN, NONE, KEY_MUHENKAN,
+ NONE, KEY_YEN, KEY_KPCOMMA, NONE,
+ /* 0x00 - 0x1f. 0xE0 prefixed */
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ KEY_PREVIOUSSONG, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, KEY_NEXTSONG, NONE, NONE,
+ NONE, KEY_KPENTER, KEY_RIGHTCTRL, NONE,
+ /* 0x20 - 0x3f. 0xE0 prefixed */
+ KEY_MUTE, KEY_CALC, KEY_PLAYPAUSE, NONE,
+ KEY_STOPCD, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, KEY_VOLUMEDOWN, NONE,
+ KEY_VOLUMEUP, NONE, KEY_HOMEPAGE, NONE,
+ NONE, KEY_KPASTERISK, NONE, KEY_SYSRQ,
+ KEY_RIGHTALT, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ /* 0x40 - 0x5f. 0xE0 prefixed */
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, KEY_PAUSE, KEY_HOME,
+ KEY_UP, KEY_PAGEUP, NONE, KEY_LEFT,
+ NONE, KEY_RIGHT, NONE, KEY_END,
+ KEY_DOWN, KEY_PAGEDOWN, KEY_INSERT, KEY_DELETE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, KEY_LEFTMETA,
+ KEY_RIGHTMETA, KEY_MENU, KEY_POWER, KEY_SLEEP,
+ /* 0x60 - 0x7f. 0xE0 prefixed */
+ NONE, NONE, NONE, KEY_WAKEUP,
+ NONE, KEY_SEARCH, KEY_BOOKMARKS, KEY_REFRESH,
+ KEY_STOP, KEY_FORWARD, KEY_BACK, KEY_COMPUTER,
+ KEY_MAIL, KEY_MEDIA, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+ NONE, NONE, NONE, NONE,
+};
+
+static uint16_t evdev_mouse_button_codes[] = {
+ BTN_LEFT,
+ BTN_MIDDLE,
+ BTN_RIGHT,
+ BTN_SIDE,
+ BTN_EXTRA,
+ BTN_FORWARD,
+ BTN_BACK,
+ BTN_TASK,
+};
+
+static uint16_t evdev_led_codes[] = {
+ LED_CAPSL, /* CLKED */
+ LED_NUML, /* NLKED */
+ LED_SCROLLL, /* SLKED */
+};
+
+inline uint16_t
+evdev_hid2key(int scancode)
+{
+ return evdev_usb_scancodes[scancode];
+}
+
+inline void
+evdev_support_all_known_keys(struct evdev_dev *evdev)
+{
+ size_t i;
+
+ for (i = KEY_RESERVED; i < nitems(evdev_at_set1_scancodes); i++)
+ if (evdev_at_set1_scancodes[i] != NONE)
+ evdev_support_key(evdev, evdev_at_set1_scancodes[i]);
+}
+
+inline uint16_t
+evdev_scancode2key(int *state, int scancode)
+{
+ uint16_t keycode;
+
+ /* translate the scan code into a keycode */
+ keycode = evdev_at_set1_scancodes[scancode & 0x7f];
+ switch (*state) {
+ case 0x00: /* normal scancode */
+ switch(scancode) {
+ case 0xE0:
+ case 0xE1:
+ *state = scancode;
+ return (NONE);
+ }
+ break;
+ case 0xE0: /* 0xE0 prefix */
+ *state = 0;
+ keycode = evdev_at_set1_scancodes[0x80 + (scancode & 0x7f)];
+ break;
+ case 0xE1: /* 0xE1 prefix */
+ /*
+ * The pause/break key on the 101 keyboard produces:
+ * E1-1D-45 E1-9D-C5
+ * Ctrl-pause/break produces:
+ * E0-46 E0-C6 (See above.)
+ */
+ *state = 0;
+ if ((scancode & 0x7f) == 0x1D)
+ *state = 0x1D;
+ return (NONE);
+ /* NOT REACHED */
+ case 0x1D: /* pause / break */
+ *state = 0;
+ if (scancode != 0x45)
+ return (NONE);
+ keycode = KEY_PAUSE;
+ break;
+ }
+
+ return (keycode);
+}
+
+void
+evdev_push_mouse_btn(struct evdev_dev *evdev, int buttons)
+{
+ size_t i;
+
+ for (i = 0; i < nitems(evdev_mouse_button_codes); i++)
+ evdev_push_event(evdev, EV_KEY, evdev_mouse_button_codes[i],
+ (buttons & (1 << i)) != 0);
+}
+
+void
+evdev_push_leds(struct evdev_dev *evdev, int leds)
+{
+ size_t i;
+
+ /* Some drivers initialize leds before evdev */
+ if (evdev == NULL)
+ return;
+
+ for (i = 0; i < nitems(evdev_led_codes); i++)
+ evdev_push_event(evdev, EV_LED, evdev_led_codes[i],
+ (leds & (1 << i)) != 0);
+}
+
+void
+evdev_push_repeats(struct evdev_dev *evdev, keyboard_t *kbd)
+{
+ /* Some drivers initialize typematics before evdev */
+ if (evdev == NULL)
+ return;
+
+ evdev_push_event(evdev, EV_REP, REP_DELAY, kbd->kb_delay1);
+ evdev_push_event(evdev, EV_REP, REP_PERIOD, kbd->kb_delay2);
+}
+
+void
+evdev_ev_kbd_event(struct evdev_dev *evdev, void *softc, uint16_t type,
+ uint16_t code, int32_t value)
+{
+ keyboard_t *kbd = (keyboard_t *)softc;
+ int delay[2], leds, oleds;
+ size_t i;
+
+ if (type == EV_LED) {
+ leds = oleds = KBD_LED_VAL(kbd);
+ for (i = 0; i < nitems(evdev_led_codes); i++) {
+ if (evdev_led_codes[i] == code) {
+ if (value)
+ leds |= 1 << i;
+ else
+ leds &= ~(1 << i);
+ if (leds != oleds)
+ kbdd_ioctl(kbd, KDSETLED,
+ (caddr_t)&leds);
+ break;
+ }
+ }
+ } else if (type == EV_REP && code == REP_DELAY) {
+ delay[0] = value;
+ delay[1] = kbd->kb_delay2;
+ kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
+ } else if (type == EV_REP && code == REP_PERIOD) {
+ delay[0] = kbd->kb_delay1;
+ delay[1] = value;
+ kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
+ }
+}
diff --git a/sys/dev/evdev/input-event-codes.h b/sys/dev/evdev/input-event-codes.h
new file mode 100644
index 0000000..78ba7d2
--- /dev/null
+++ b/sys/dev/evdev/input-event-codes.h
@@ -0,0 +1,819 @@
+/*-
+ * Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
+ * 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 _EVDEV_INPUT_EVENT_CODES_H
+#define _EVDEV_INPUT_EVENT_CODES_H
+
+/*
+ * Device properties and quirks
+ */
+
+#define INPUT_PROP_POINTER 0x00 /* needs a pointer */
+#define INPUT_PROP_DIRECT 0x01 /* direct input devices */
+#define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */
+#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */
+#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
+#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */
+#define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */
+
+#define INPUT_PROP_MAX 0x1f
+#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
+
+/*
+ * Event types
+ */
+
+#define EV_SYN 0x00
+#define EV_KEY 0x01
+#define EV_REL 0x02
+#define EV_ABS 0x03
+#define EV_MSC 0x04
+#define EV_SW 0x05
+#define EV_LED 0x11
+#define EV_SND 0x12
+#define EV_REP 0x14
+#define EV_FF 0x15
+#define EV_PWR 0x16
+#define EV_FF_STATUS 0x17
+#define EV_MAX 0x1f
+#define EV_CNT (EV_MAX+1)
+
+/*
+ * Synchronization events.
+ */
+
+#define SYN_REPORT 0
+#define SYN_CONFIG 1
+#define SYN_MT_REPORT 2
+#define SYN_DROPPED 3
+#define SYN_MAX 0xf
+#define SYN_CNT (SYN_MAX+1)
+
+/*
+ * Keys and buttons
+ */
+
+/*
+ * Abbreviations in the comments:
+ * AC - Application Control
+ * AL - Application Launch Button
+ * SC - System Control
+ */
+
+#define KEY_RESERVED 0
+#define KEY_ESC 1
+#define KEY_1 2
+#define KEY_2 3
+#define KEY_3 4
+#define KEY_4 5
+#define KEY_5 6
+#define KEY_6 7
+#define KEY_7 8
+#define KEY_8 9
+#define KEY_9 10
+#define KEY_0 11
+#define KEY_MINUS 12
+#define KEY_EQUAL 13
+#define KEY_BACKSPACE 14
+#define KEY_TAB 15
+#define KEY_Q 16
+#define KEY_W 17
+#define KEY_E 18
+#define KEY_R 19
+#define KEY_T 20
+#define KEY_Y 21
+#define KEY_U 22
+#define KEY_I 23
+#define KEY_O 24
+#define KEY_P 25
+#define KEY_LEFTBRACE 26
+#define KEY_RIGHTBRACE 27
+#define KEY_ENTER 28
+#define KEY_LEFTCTRL 29
+#define KEY_A 30
+#define KEY_S 31
+#define KEY_D 32
+#define KEY_F 33
+#define KEY_G 34
+#define KEY_H 35
+#define KEY_J 36
+#define KEY_K 37
+#define KEY_L 38
+#define KEY_SEMICOLON 39
+#define KEY_APOSTROPHE 40
+#define KEY_GRAVE 41
+#define KEY_LEFTSHIFT 42
+#define KEY_BACKSLASH 43
+#define KEY_Z 44
+#define KEY_X 45
+#define KEY_C 46
+#define KEY_V 47
+#define KEY_B 48
+#define KEY_N 49
+#define KEY_M 50
+#define KEY_COMMA 51
+#define KEY_DOT 52
+#define KEY_SLASH 53
+#define KEY_RIGHTSHIFT 54
+#define KEY_KPASTERISK 55
+#define KEY_LEFTALT 56
+#define KEY_SPACE 57
+#define KEY_CAPSLOCK 58
+#define KEY_F1 59
+#define KEY_F2 60
+#define KEY_F3 61
+#define KEY_F4 62
+#define KEY_F5 63
+#define KEY_F6 64
+#define KEY_F7 65
+#define KEY_F8 66
+#define KEY_F9 67
+#define KEY_F10 68
+#define KEY_NUMLOCK 69
+#define KEY_SCROLLLOCK 70
+#define KEY_KP7 71
+#define KEY_KP8 72
+#define KEY_KP9 73
+#define KEY_KPMINUS 74
+#define KEY_KP4 75
+#define KEY_KP5 76
+#define KEY_KP6 77
+#define KEY_KPPLUS 78
+#define KEY_KP1 79
+#define KEY_KP2 80
+#define KEY_KP3 81
+#define KEY_KP0 82
+#define KEY_KPDOT 83
+
+#define KEY_ZENKAKUHANKAKU 85
+#define KEY_102ND 86
+#define KEY_F11 87
+#define KEY_F12 88
+#define KEY_RO 89
+#define KEY_KATAKANA 90
+#define KEY_HIRAGANA 91
+#define KEY_HENKAN 92
+#define KEY_KATAKANAHIRAGANA 93
+#define KEY_MUHENKAN 94
+#define KEY_KPJPCOMMA 95
+#define KEY_KPENTER 96
+#define KEY_RIGHTCTRL 97
+#define KEY_KPSLASH 98
+#define KEY_SYSRQ 99
+#define KEY_RIGHTALT 100
+#define KEY_LINEFEED 101
+#define KEY_HOME 102
+#define KEY_UP 103
+#define KEY_PAGEUP 104
+#define KEY_LEFT 105
+#define KEY_RIGHT 106
+#define KEY_END 107
+#define KEY_DOWN 108
+#define KEY_PAGEDOWN 109
+#define KEY_INSERT 110
+#define KEY_DELETE 111
+#define KEY_MACRO 112
+#define KEY_MUTE 113
+#define KEY_VOLUMEDOWN 114
+#define KEY_VOLUMEUP 115
+#define KEY_POWER 116 /* SC System Power Down */
+#define KEY_KPEQUAL 117
+#define KEY_KPPLUSMINUS 118
+#define KEY_PAUSE 119
+#define KEY_SCALE 120 /* AL Compiz Scale (Expose) */
+
+#define KEY_KPCOMMA 121
+#define KEY_HANGEUL 122
+#define KEY_HANGUEL KEY_HANGEUL
+#define KEY_HANJA 123
+#define KEY_YEN 124
+#define KEY_LEFTMETA 125
+#define KEY_RIGHTMETA 126
+#define KEY_COMPOSE 127
+
+#define KEY_STOP 128 /* AC Stop */
+#define KEY_AGAIN 129
+#define KEY_PROPS 130 /* AC Properties */
+#define KEY_UNDO 131 /* AC Undo */
+#define KEY_FRONT 132
+#define KEY_COPY 133 /* AC Copy */
+#define KEY_OPEN 134 /* AC Open */
+#define KEY_PASTE 135 /* AC Paste */
+#define KEY_FIND 136 /* AC Search */
+#define KEY_CUT 137 /* AC Cut */
+#define KEY_HELP 138 /* AL Integrated Help Center */
+#define KEY_MENU 139 /* Menu (show menu) */
+#define KEY_CALC 140 /* AL Calculator */
+#define KEY_SETUP 141
+#define KEY_SLEEP 142 /* SC System Sleep */
+#define KEY_WAKEUP 143 /* System Wake Up */
+#define KEY_FILE 144 /* AL Local Machine Browser */
+#define KEY_SENDFILE 145
+#define KEY_DELETEFILE 146
+#define KEY_XFER 147
+#define KEY_PROG1 148
+#define KEY_PROG2 149
+#define KEY_WWW 150 /* AL Internet Browser */
+#define KEY_MSDOS 151
+#define KEY_COFFEE 152 /* AL Terminal Lock/Screensaver */
+#define KEY_SCREENLOCK KEY_COFFEE
+#define KEY_ROTATE_DISPLAY 153 /* Display orientation for e.g. tablets */
+#define KEY_DIRECTION KEY_ROTATE_DISPLAY
+#define KEY_CYCLEWINDOWS 154
+#define KEY_MAIL 155
+#define KEY_BOOKMARKS 156 /* AC Bookmarks */
+#define KEY_COMPUTER 157
+#define KEY_BACK 158 /* AC Back */
+#define KEY_FORWARD 159 /* AC Forward */
+#define KEY_CLOSECD 160
+#define KEY_EJECTCD 161
+#define KEY_EJECTCLOSECD 162
+#define KEY_NEXTSONG 163
+#define KEY_PLAYPAUSE 164
+#define KEY_PREVIOUSSONG 165
+#define KEY_STOPCD 166
+#define KEY_RECORD 167
+#define KEY_REWIND 168
+#define KEY_PHONE 169 /* Media Select Telephone */
+#define KEY_ISO 170
+#define KEY_CONFIG 171 /* AL Consumer Control Configuration */
+#define KEY_HOMEPAGE 172 /* AC Home */
+#define KEY_REFRESH 173 /* AC Refresh */
+#define KEY_EXIT 174 /* AC Exit */
+#define KEY_MOVE 175
+#define KEY_EDIT 176
+#define KEY_SCROLLUP 177
+#define KEY_SCROLLDOWN 178
+#define KEY_KPLEFTPAREN 179
+#define KEY_KPRIGHTPAREN 180
+#define KEY_NEW 181 /* AC New */
+#define KEY_REDO 182 /* AC Redo/Repeat */
+
+#define KEY_F13 183
+#define KEY_F14 184
+#define KEY_F15 185
+#define KEY_F16 186
+#define KEY_F17 187
+#define KEY_F18 188
+#define KEY_F19 189
+#define KEY_F20 190
+#define KEY_F21 191
+#define KEY_F22 192
+#define KEY_F23 193
+#define KEY_F24 194
+
+#define KEY_PLAYCD 200
+#define KEY_PAUSECD 201
+#define KEY_PROG3 202
+#define KEY_PROG4 203
+#define KEY_DASHBOARD 204 /* AL Dashboard */
+#define KEY_SUSPEND 205
+#define KEY_CLOSE 206 /* AC Close */
+#define KEY_PLAY 207
+#define KEY_FASTFORWARD 208
+#define KEY_BASSBOOST 209
+#define KEY_PRINT 210 /* AC Print */
+#define KEY_HP 211
+#define KEY_CAMERA 212
+#define KEY_SOUND 213
+#define KEY_QUESTION 214
+#define KEY_EMAIL 215
+#define KEY_CHAT 216
+#define KEY_SEARCH 217
+#define KEY_CONNECT 218
+#define KEY_FINANCE 219 /* AL Checkbook/Finance */
+#define KEY_SPORT 220
+#define KEY_SHOP 221
+#define KEY_ALTERASE 222
+#define KEY_CANCEL 223 /* AC Cancel */
+#define KEY_BRIGHTNESSDOWN 224
+#define KEY_BRIGHTNESSUP 225
+#define KEY_MEDIA 226
+
+#define KEY_SWITCHVIDEOMODE 227 /* Cycle between available video
+ outputs (Monitor/LCD/TV-out/etc) */
+#define KEY_KBDILLUMTOGGLE 228
+#define KEY_KBDILLUMDOWN 229
+#define KEY_KBDILLUMUP 230
+
+#define KEY_SEND 231 /* AC Send */
+#define KEY_REPLY 232 /* AC Reply */
+#define KEY_FORWARDMAIL 233 /* AC Forward Msg */
+#define KEY_SAVE 234 /* AC Save */
+#define KEY_DOCUMENTS 235
+
+#define KEY_BATTERY 236
+
+#define KEY_BLUETOOTH 237
+#define KEY_WLAN 238
+#define KEY_UWB 239
+
+#define KEY_UNKNOWN 240
+
+#define KEY_VIDEO_NEXT 241 /* drive next video source */
+#define KEY_VIDEO_PREV 242 /* drive previous video source */
+#define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */
+#define KEY_BRIGHTNESS_AUTO 244 /* Set Auto Brightness: manual
+ brightness control is off,
+ rely on ambient */
+#define KEY_BRIGHTNESS_ZERO KEY_BRIGHTNESS_AUTO
+#define KEY_DISPLAY_OFF 245 /* display device to off state */
+
+#define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */
+#define KEY_WIMAX KEY_WWAN
+#define KEY_RFKILL 247 /* Key that controls all radios */
+
+#define KEY_MICMUTE 248 /* Mute / unmute the microphone */
+
+/* Code 255 is reserved for special needs of AT keyboard driver */
+
+#define BTN_MISC 0x100
+#define BTN_0 0x100
+#define BTN_1 0x101
+#define BTN_2 0x102
+#define BTN_3 0x103
+#define BTN_4 0x104
+#define BTN_5 0x105
+#define BTN_6 0x106
+#define BTN_7 0x107
+#define BTN_8 0x108
+#define BTN_9 0x109
+
+#define BTN_MOUSE 0x110
+#define BTN_LEFT 0x110
+#define BTN_RIGHT 0x111
+#define BTN_MIDDLE 0x112
+#define BTN_SIDE 0x113
+#define BTN_EXTRA 0x114
+#define BTN_FORWARD 0x115
+#define BTN_BACK 0x116
+#define BTN_TASK 0x117
+
+#define BTN_JOYSTICK 0x120
+#define BTN_TRIGGER 0x120
+#define BTN_THUMB 0x121
+#define BTN_THUMB2 0x122
+#define BTN_TOP 0x123
+#define BTN_TOP2 0x124
+#define BTN_PINKIE 0x125
+#define BTN_BASE 0x126
+#define BTN_BASE2 0x127
+#define BTN_BASE3 0x128
+#define BTN_BASE4 0x129
+#define BTN_BASE5 0x12a
+#define BTN_BASE6 0x12b
+#define BTN_DEAD 0x12f
+
+#define BTN_GAMEPAD 0x130
+#define BTN_SOUTH 0x130
+#define BTN_A BTN_SOUTH
+#define BTN_EAST 0x131
+#define BTN_B BTN_EAST
+#define BTN_C 0x132
+#define BTN_NORTH 0x133
+#define BTN_X BTN_NORTH
+#define BTN_WEST 0x134
+#define BTN_Y BTN_WEST
+#define BTN_Z 0x135
+#define BTN_TL 0x136
+#define BTN_TR 0x137
+#define BTN_TL2 0x138
+#define BTN_TR2 0x139
+#define BTN_SELECT 0x13a
+#define BTN_START 0x13b
+#define BTN_MODE 0x13c
+#define BTN_THUMBL 0x13d
+#define BTN_THUMBR 0x13e
+
+#define BTN_DIGI 0x140
+#define BTN_TOOL_PEN 0x140
+#define BTN_TOOL_RUBBER 0x141
+#define BTN_TOOL_BRUSH 0x142
+#define BTN_TOOL_PENCIL 0x143
+#define BTN_TOOL_AIRBRUSH 0x144
+#define BTN_TOOL_FINGER 0x145
+#define BTN_TOOL_MOUSE 0x146
+#define BTN_TOOL_LENS 0x147
+#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */
+#define BTN_TOUCH 0x14a
+#define BTN_STYLUS 0x14b
+#define BTN_STYLUS2 0x14c
+#define BTN_TOOL_DOUBLETAP 0x14d
+#define BTN_TOOL_TRIPLETAP 0x14e
+#define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad */
+
+#define BTN_WHEEL 0x150
+#define BTN_GEAR_DOWN 0x150
+#define BTN_GEAR_UP 0x151
+
+#define KEY_OK 0x160
+#define KEY_SELECT 0x161
+#define KEY_GOTO 0x162
+#define KEY_CLEAR 0x163
+#define KEY_POWER2 0x164
+#define KEY_OPTION 0x165
+#define KEY_INFO 0x166 /* AL OEM Features/Tips/Tutorial */
+#define KEY_TIME 0x167
+#define KEY_VENDOR 0x168
+#define KEY_ARCHIVE 0x169
+#define KEY_PROGRAM 0x16a /* Media Select Program Guide */
+#define KEY_CHANNEL 0x16b
+#define KEY_FAVORITES 0x16c
+#define KEY_EPG 0x16d
+#define KEY_PVR 0x16e /* Media Select Home */
+#define KEY_MHP 0x16f
+#define KEY_LANGUAGE 0x170
+#define KEY_TITLE 0x171
+#define KEY_SUBTITLE 0x172
+#define KEY_ANGLE 0x173
+#define KEY_ZOOM 0x174
+#define KEY_MODE 0x175
+#define KEY_KEYBOARD 0x176
+#define KEY_SCREEN 0x177
+#define KEY_PC 0x178 /* Media Select Computer */
+#define KEY_TV 0x179 /* Media Select TV */
+#define KEY_TV2 0x17a /* Media Select Cable */
+#define KEY_VCR 0x17b /* Media Select VCR */
+#define KEY_VCR2 0x17c /* VCR Plus */
+#define KEY_SAT 0x17d /* Media Select Satellite */
+#define KEY_SAT2 0x17e
+#define KEY_CD 0x17f /* Media Select CD */
+#define KEY_TAPE 0x180 /* Media Select Tape */
+#define KEY_RADIO 0x181
+#define KEY_TUNER 0x182 /* Media Select Tuner */
+#define KEY_PLAYER 0x183
+#define KEY_TEXT 0x184
+#define KEY_DVD 0x185 /* Media Select DVD */
+#define KEY_AUX 0x186
+#define KEY_MP3 0x187
+#define KEY_AUDIO 0x188 /* AL Audio Browser */
+#define KEY_VIDEO 0x189 /* AL Movie Browser */
+#define KEY_DIRECTORY 0x18a
+#define KEY_LIST 0x18b
+#define KEY_MEMO 0x18c /* Media Select Messages */
+#define KEY_CALENDAR 0x18d
+#define KEY_RED 0x18e
+#define KEY_GREEN 0x18f
+#define KEY_YELLOW 0x190
+#define KEY_BLUE 0x191
+#define KEY_CHANNELUP 0x192 /* Channel Increment */
+#define KEY_CHANNELDOWN 0x193 /* Channel Decrement */
+#define KEY_FIRST 0x194
+#define KEY_LAST 0x195 /* Recall Last */
+#define KEY_AB 0x196
+#define KEY_NEXT 0x197
+#define KEY_RESTART 0x198
+#define KEY_SLOW 0x199
+#define KEY_SHUFFLE 0x19a
+#define KEY_BREAK 0x19b
+#define KEY_PREVIOUS 0x19c
+#define KEY_DIGITS 0x19d
+#define KEY_TEEN 0x19e
+#define KEY_TWEN 0x19f
+#define KEY_VIDEOPHONE 0x1a0 /* Media Select Video Phone */
+#define KEY_GAMES 0x1a1 /* Media Select Games */
+#define KEY_ZOOMIN 0x1a2 /* AC Zoom In */
+#define KEY_ZOOMOUT 0x1a3 /* AC Zoom Out */
+#define KEY_ZOOMRESET 0x1a4 /* AC Zoom */
+#define KEY_WORDPROCESSOR 0x1a5 /* AL Word Processor */
+#define KEY_EDITOR 0x1a6 /* AL Text Editor */
+#define KEY_SPREADSHEET 0x1a7 /* AL Spreadsheet */
+#define KEY_GRAPHICSEDITOR 0x1a8 /* AL Graphics Editor */
+#define KEY_PRESENTATION 0x1a9 /* AL Presentation App */
+#define KEY_DATABASE 0x1aa /* AL Database App */
+#define KEY_NEWS 0x1ab /* AL Newsreader */
+#define KEY_VOICEMAIL 0x1ac /* AL Voicemail */
+#define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */
+#define KEY_MESSENGER 0x1ae /* AL Instant Messaging */
+#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */
+#define KEY_BRIGHTNESS_TOGGLE KEY_DISPLAYTOGGLE
+#define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */
+#define KEY_LOGOFF 0x1b1 /* AL Logoff */
+
+#define KEY_DOLLAR 0x1b2
+#define KEY_EURO 0x1b3
+
+#define KEY_FRAMEBACK 0x1b4 /* Consumer - transport controls */
+#define KEY_FRAMEFORWARD 0x1b5
+#define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */
+#define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */
+#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */
+#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */
+#define KEY_IMAGES 0x1ba /* AL Image Browser */
+
+#define KEY_DEL_EOL 0x1c0
+#define KEY_DEL_EOS 0x1c1
+#define KEY_INS_LINE 0x1c2
+#define KEY_DEL_LINE 0x1c3
+
+#define KEY_FN 0x1d0
+#define KEY_FN_ESC 0x1d1
+#define KEY_FN_F1 0x1d2
+#define KEY_FN_F2 0x1d3
+#define KEY_FN_F3 0x1d4
+#define KEY_FN_F4 0x1d5
+#define KEY_FN_F5 0x1d6
+#define KEY_FN_F6 0x1d7
+#define KEY_FN_F7 0x1d8
+#define KEY_FN_F8 0x1d9
+#define KEY_FN_F9 0x1da
+#define KEY_FN_F10 0x1db
+#define KEY_FN_F11 0x1dc
+#define KEY_FN_F12 0x1dd
+#define KEY_FN_1 0x1de
+#define KEY_FN_2 0x1df
+#define KEY_FN_D 0x1e0
+#define KEY_FN_E 0x1e1
+#define KEY_FN_F 0x1e2
+#define KEY_FN_S 0x1e3
+#define KEY_FN_B 0x1e4
+
+#define KEY_BRL_DOT1 0x1f1
+#define KEY_BRL_DOT2 0x1f2
+#define KEY_BRL_DOT3 0x1f3
+#define KEY_BRL_DOT4 0x1f4
+#define KEY_BRL_DOT5 0x1f5
+#define KEY_BRL_DOT6 0x1f6
+#define KEY_BRL_DOT7 0x1f7
+#define KEY_BRL_DOT8 0x1f8
+#define KEY_BRL_DOT9 0x1f9
+#define KEY_BRL_DOT10 0x1fa
+
+#define KEY_NUMERIC_0 0x200 /* used by phones, remote controls, */
+#define KEY_NUMERIC_1 0x201 /* and other keypads */
+#define KEY_NUMERIC_2 0x202
+#define KEY_NUMERIC_3 0x203
+#define KEY_NUMERIC_4 0x204
+#define KEY_NUMERIC_5 0x205
+#define KEY_NUMERIC_6 0x206
+#define KEY_NUMERIC_7 0x207
+#define KEY_NUMERIC_8 0x208
+#define KEY_NUMERIC_9 0x209
+#define KEY_NUMERIC_STAR 0x20a
+#define KEY_NUMERIC_POUND 0x20b
+#define KEY_NUMERIC_A 0x20c /* Phone key A - HUT Telephony 0xb9 */
+#define KEY_NUMERIC_B 0x20d
+#define KEY_NUMERIC_C 0x20e
+#define KEY_NUMERIC_D 0x20f
+
+#define KEY_CAMERA_FOCUS 0x210
+#define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */
+
+#define KEY_TOUCHPAD_TOGGLE 0x212 /* Request switch touchpad on or off */
+#define KEY_TOUCHPAD_ON 0x213
+#define KEY_TOUCHPAD_OFF 0x214
+
+#define KEY_CAMERA_ZOOMIN 0x215
+#define KEY_CAMERA_ZOOMOUT 0x216
+#define KEY_CAMERA_UP 0x217
+#define KEY_CAMERA_DOWN 0x218
+#define KEY_CAMERA_LEFT 0x219
+#define KEY_CAMERA_RIGHT 0x21a
+
+#define KEY_ATTENDANT_ON 0x21b
+#define KEY_ATTENDANT_OFF 0x21c
+#define KEY_ATTENDANT_TOGGLE 0x21d /* Attendant call on or off */
+#define KEY_LIGHTS_TOGGLE 0x21e /* Reading light on or off */
+
+#define BTN_DPAD_UP 0x220
+#define BTN_DPAD_DOWN 0x221
+#define BTN_DPAD_LEFT 0x222
+#define BTN_DPAD_RIGHT 0x223
+
+#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
+
+#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
+#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
+#define KEY_JOURNAL 0x242 /* AL Log/Journal/Timecard */
+#define KEY_CONTROLPANEL 0x243 /* AL Control Panel */
+#define KEY_APPSELECT 0x244 /* AL Select Task/Application */
+#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
+#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
+
+#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
+#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
+
+#define KEY_KBDINPUTASSIST_PREV 0x260
+#define KEY_KBDINPUTASSIST_NEXT 0x261
+#define KEY_KBDINPUTASSIST_PREVGROUP 0x262
+#define KEY_KBDINPUTASSIST_NEXTGROUP 0x263
+#define KEY_KBDINPUTASSIST_ACCEPT 0x264
+#define KEY_KBDINPUTASSIST_CANCEL 0x265
+
+#define BTN_TRIGGER_HAPPY 0x2c0
+#define BTN_TRIGGER_HAPPY1 0x2c0
+#define BTN_TRIGGER_HAPPY2 0x2c1
+#define BTN_TRIGGER_HAPPY3 0x2c2
+#define BTN_TRIGGER_HAPPY4 0x2c3
+#define BTN_TRIGGER_HAPPY5 0x2c4
+#define BTN_TRIGGER_HAPPY6 0x2c5
+#define BTN_TRIGGER_HAPPY7 0x2c6
+#define BTN_TRIGGER_HAPPY8 0x2c7
+#define BTN_TRIGGER_HAPPY9 0x2c8
+#define BTN_TRIGGER_HAPPY10 0x2c9
+#define BTN_TRIGGER_HAPPY11 0x2ca
+#define BTN_TRIGGER_HAPPY12 0x2cb
+#define BTN_TRIGGER_HAPPY13 0x2cc
+#define BTN_TRIGGER_HAPPY14 0x2cd
+#define BTN_TRIGGER_HAPPY15 0x2ce
+#define BTN_TRIGGER_HAPPY16 0x2cf
+#define BTN_TRIGGER_HAPPY17 0x2d0
+#define BTN_TRIGGER_HAPPY18 0x2d1
+#define BTN_TRIGGER_HAPPY19 0x2d2
+#define BTN_TRIGGER_HAPPY20 0x2d3
+#define BTN_TRIGGER_HAPPY21 0x2d4
+#define BTN_TRIGGER_HAPPY22 0x2d5
+#define BTN_TRIGGER_HAPPY23 0x2d6
+#define BTN_TRIGGER_HAPPY24 0x2d7
+#define BTN_TRIGGER_HAPPY25 0x2d8
+#define BTN_TRIGGER_HAPPY26 0x2d9
+#define BTN_TRIGGER_HAPPY27 0x2da
+#define BTN_TRIGGER_HAPPY28 0x2db
+#define BTN_TRIGGER_HAPPY29 0x2dc
+#define BTN_TRIGGER_HAPPY30 0x2dd
+#define BTN_TRIGGER_HAPPY31 0x2de
+#define BTN_TRIGGER_HAPPY32 0x2df
+#define BTN_TRIGGER_HAPPY33 0x2e0
+#define BTN_TRIGGER_HAPPY34 0x2e1
+#define BTN_TRIGGER_HAPPY35 0x2e2
+#define BTN_TRIGGER_HAPPY36 0x2e3
+#define BTN_TRIGGER_HAPPY37 0x2e4
+#define BTN_TRIGGER_HAPPY38 0x2e5
+#define BTN_TRIGGER_HAPPY39 0x2e6
+#define BTN_TRIGGER_HAPPY40 0x2e7
+
+/* We avoid low common keys in module aliases so they don't get huge. */
+#define KEY_MIN_INTERESTING KEY_MUTE
+#define KEY_MAX 0x2ff
+#define KEY_CNT (KEY_MAX+1)
+
+/*
+ * Relative axes
+ */
+
+#define REL_X 0x00
+#define REL_Y 0x01
+#define REL_Z 0x02
+#define REL_RX 0x03
+#define REL_RY 0x04
+#define REL_RZ 0x05
+#define REL_HWHEEL 0x06
+#define REL_DIAL 0x07
+#define REL_WHEEL 0x08
+#define REL_MISC 0x09
+#define REL_MAX 0x0f
+#define REL_CNT (REL_MAX+1)
+
+/*
+ * Absolute axes
+ */
+
+#define ABS_X 0x00
+#define ABS_Y 0x01
+#define ABS_Z 0x02
+#define ABS_RX 0x03
+#define ABS_RY 0x04
+#define ABS_RZ 0x05
+#define ABS_THROTTLE 0x06
+#define ABS_RUDDER 0x07
+#define ABS_WHEEL 0x08
+#define ABS_GAS 0x09
+#define ABS_BRAKE 0x0a
+#define ABS_HAT0X 0x10
+#define ABS_HAT0Y 0x11
+#define ABS_HAT1X 0x12
+#define ABS_HAT1Y 0x13
+#define ABS_HAT2X 0x14
+#define ABS_HAT2Y 0x15
+#define ABS_HAT3X 0x16
+#define ABS_HAT3Y 0x17
+#define ABS_PRESSURE 0x18
+#define ABS_DISTANCE 0x19
+#define ABS_TILT_X 0x1a
+#define ABS_TILT_Y 0x1b
+#define ABS_TOOL_WIDTH 0x1c
+
+#define ABS_VOLUME 0x20
+
+#define ABS_MISC 0x28
+
+#define ABS_MT_SLOT 0x2f /* MT slot being modified */
+#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
+#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
+#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
+#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
+#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
+#define ABS_MT_POSITION_X 0x35 /* Center X touch position */
+#define ABS_MT_POSITION_Y 0x36 /* Center Y touch position */
+#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
+#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
+#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
+#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
+#define ABS_MT_DISTANCE 0x3b /* Contact hover distance */
+#define ABS_MT_TOOL_X 0x3c /* Center X tool position */
+#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
+
+#define ABS_MAX 0x3f
+#define ABS_CNT (ABS_MAX+1)
+
+/*
+ * Switch events
+ */
+
+#define SW_LID 0x00 /* set = lid shut */
+#define SW_TABLET_MODE 0x01 /* set = tablet mode */
+#define SW_HEADPHONE_INSERT 0x02 /* set = inserted */
+#define SW_RFKILL_ALL 0x03 /* rfkill master switch, type "any"
+ set = radio enabled */
+#define SW_RADIO SW_RFKILL_ALL /* deprecated */
+#define SW_MICROPHONE_INSERT 0x04 /* set = inserted */
+#define SW_DOCK 0x05 /* set = plugged into dock */
+#define SW_LINEOUT_INSERT 0x06 /* set = inserted */
+#define SW_JACK_PHYSICAL_INSERT 0x07 /* set = mechanical switch set */
+#define SW_VIDEOOUT_INSERT 0x08 /* set = inserted */
+#define SW_CAMERA_LENS_COVER 0x09 /* set = lens covered */
+#define SW_KEYPAD_SLIDE 0x0a /* set = keypad slide out */
+#define SW_FRONT_PROXIMITY 0x0b /* set = front proximity sensor active */
+#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
+#define SW_LINEIN_INSERT 0x0d /* set = inserted */
+#define SW_MUTE_DEVICE 0x0e /* set = device disabled */
+#define SW_MAX 0x0f
+#define SW_CNT (SW_MAX+1)
+
+/*
+ * Misc events
+ */
+
+#define MSC_SERIAL 0x00
+#define MSC_PULSELED 0x01
+#define MSC_GESTURE 0x02
+#define MSC_RAW 0x03
+#define MSC_SCAN 0x04
+#define MSC_TIMESTAMP 0x05
+#define MSC_MAX 0x07
+#define MSC_CNT (MSC_MAX+1)
+
+/*
+ * LEDs
+ */
+
+#define LED_NUML 0x00
+#define LED_CAPSL 0x01
+#define LED_SCROLLL 0x02
+#define LED_COMPOSE 0x03
+#define LED_KANA 0x04
+#define LED_SLEEP 0x05
+#define LED_SUSPEND 0x06
+#define LED_MUTE 0x07
+#define LED_MISC 0x08
+#define LED_MAIL 0x09
+#define LED_CHARGING 0x0a
+#define LED_MAX 0x0f
+#define LED_CNT (LED_MAX+1)
+
+/*
+ * Autorepeat values
+ */
+
+#define REP_DELAY 0x00
+#define REP_PERIOD 0x01
+#define REP_MAX 0x01
+#define REP_CNT (REP_MAX+1)
+
+/*
+ * Sounds
+ */
+
+#define SND_CLICK 0x00
+#define SND_BELL 0x01
+#define SND_TONE 0x02
+#define SND_MAX 0x07
+#define SND_CNT (SND_MAX+1)
+
+#endif /* _EVDEV_INPUT_EVENT_CODES_H */
diff --git a/sys/dev/evdev/input.h b/sys/dev/evdev/input.h
new file mode 100644
index 0000000..0463844
--- /dev/null
+++ b/sys/dev/evdev/input.h
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
+ * 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 _EVDEV_INPUT_H
+#define _EVDEV_INPUT_H
+
+#ifndef __KERNEL__
+#include <sys/time.h>
+#include <sys/ioccom.h>
+#include <sys/types.h>
+#endif
+
+#include "input-event-codes.h"
+
+struct input_event {
+ struct timeval time;
+ uint16_t type;
+ uint16_t code;
+ int32_t value;
+};
+
+#define EV_VERSION 0x010001
+
+struct input_id {
+ uint16_t bustype;
+ uint16_t vendor;
+ uint16_t product;
+ uint16_t version;
+};
+
+struct input_absinfo {
+ int32_t value;
+ int32_t minimum;
+ int32_t maximum;
+ int32_t fuzz;
+ int32_t flat;
+ int32_t resolution;
+};
+
+#define INPUT_KEYMAP_BY_INDEX (1 << 0)
+
+struct input_keymap_entry {
+ uint8_t flags;
+ uint8_t len;
+ uint16_t index;
+ uint32_t keycode;
+ uint8_t scancode[32];
+};
+
+#define EVDEV_IOC_MAGIC 'E'
+#define EVIOCGVERSION _IOR(EVDEV_IOC_MAGIC, 0x01, int) /* get driver version */
+#define EVIOCGID _IOR(EVDEV_IOC_MAGIC, 0x02, struct input_id) /* get device ID */
+#define EVIOCGREP _IOR(EVDEV_IOC_MAGIC, 0x03, unsigned int[2]) /* get repeat settings */
+#define EVIOCSREP _IOW(EVDEV_IOC_MAGIC, 0x03, unsigned int[2]) /* set repeat settings */
+
+#define EVIOCGKEYCODE _IOWR(EVDEV_IOC_MAGIC, 0x04, unsigned int[2]) /* get keycode */
+#define EVIOCGKEYCODE_V2 _IOWR(EVDEV_IOC_MAGIC, 0x04, struct input_keymap_entry)
+#define EVIOCSKEYCODE _IOW(EVDEV_IOC_MAGIC, 0x04, unsigned int[2]) /* set keycode */
+#define EVIOCSKEYCODE_V2 _IOW(EVDEV_IOC_MAGIC, 0x04, struct input_keymap_entry)
+
+#define EVIOCGNAME(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x06, len) /* get device name */
+#define EVIOCGPHYS(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x07, len) /* get physical location */
+#define EVIOCGUNIQ(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x08, len) /* get unique identifier */
+#define EVIOCGPROP(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x09, len) /* get device properties */
+
+#define EVIOCGMTSLOTS(len) _IOC(IOC_INOUT, EVDEV_IOC_MAGIC, 0x0a, len) /* get MT slots values */
+
+#define EVIOCGKEY(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x18, len) /* get global key state */
+#define EVIOCGLED(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x19, len) /* get all LEDs */
+#define EVIOCGSND(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x1a, len) /* get all sounds status */
+#define EVIOCGSW(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x1b, len) /* get all switch states */
+
+#define EVIOCGBIT(ev,len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x20 + (ev), len) /* get event bits */
+#define EVIOCGABS(abs) _IOR(EVDEV_IOC_MAGIC, 0x40 + (abs), struct input_absinfo) /* get abs value/limits */
+#define EVIOCSABS(abs) _IOW(EVDEV_IOC_MAGIC, 0xc0 + (abs), struct input_absinfo) /* set abs value/limits */
+
+#define EVIOCSFF _IOW(EVDEV_IOC_MAGIC, 0x80, struct ff_effect) /* send a force effect to a force feedback device */
+#define EVIOCRMFF _IOWINT(EVDEV_IOC_MAGIC, 0x81) /* Erase a force effect */
+#define EVIOCGEFFECTS _IOR(EVDEV_IOC_MAGIC, 0x84, int) /* Report number of effects playable at the same time */
+
+#define EVIOCGRAB _IOWINT(EVDEV_IOC_MAGIC, 0x90) /* Grab/Release device */
+#define EVIOCREVOKE _IOWINT(EVDEV_IOC_MAGIC, 0x91) /* Revoke device access */
+
+#define EVIOCSCLOCKID _IOW(EVDEV_IOC_MAGIC, 0xa0, int) /* Set clockid to be used for timestamps */
+
+/*
+ * IDs.
+ */
+
+#define ID_BUS 0
+#define ID_VENDOR 1
+#define ID_PRODUCT 2
+#define ID_VERSION 3
+
+#define BUS_PCI 0x01
+#define BUS_ISAPNP 0x02
+#define BUS_USB 0x03
+#define BUS_HIL 0x04
+#define BUS_BLUETOOTH 0x05
+#define BUS_VIRTUAL 0x06
+
+#define BUS_ISA 0x10
+#define BUS_I8042 0x11
+#define BUS_XTKBD 0x12
+#define BUS_RS232 0x13
+#define BUS_GAMEPORT 0x14
+#define BUS_PARPORT 0x15
+#define BUS_AMIGA 0x16
+#define BUS_ADB 0x17
+#define BUS_I2C 0x18
+#define BUS_HOST 0x19
+#define BUS_GSC 0x1A
+#define BUS_ATARI 0x1B
+#define BUS_SPI 0x1C
+
+/*
+ * MT_TOOL types
+ */
+#define MT_TOOL_FINGER 0
+#define MT_TOOL_PEN 1
+#define MT_TOOL_PALM 2
+#define MT_TOOL_MAX 2
+
+/*
+ * Values describing the status of a force-feedback effect
+ */
+#define FF_STATUS_STOPPED 0x00
+#define FF_STATUS_PLAYING 0x01
+#define FF_STATUS_MAX 0x01
+
+/* scheduling info for force feedback effect */
+struct ff_replay {
+ uint16_t length; /* length of the effect (ms) */
+ uint16_t delay; /* delay before effect starts (ms) */
+};
+
+/* trigger for force feedback effect */
+struct ff_trigger {
+ uint16_t button; /* trigger button number */
+ uint16_t interval; /* delay between re-triggers */
+};
+
+/* force feedback effect envelop */
+struct ff_envelope {
+ uint16_t attack_length; /* duration of the attach (ms) */
+ uint16_t attack_level; /* level at the beginning (0x0000 - 0x7fff) */
+ uint16_t fade_length; /* duratin of fade (ms) */
+ uint16_t fade_level; /* level at the end of fade */
+};
+
+struct ff_constant_effect {
+ int16_t level;
+ struct ff_envelope envelope;
+};
+
+struct ff_ramp_effect {
+ int16_t start_level;
+ int16_t end_level;
+ struct ff_envelope envelope;
+};
+
+struct ff_condition_effect {
+ /* maximum level when joystick moved to respective side */
+ uint16_t right_saturation;
+
+ uint16_t left_saturation;
+ /* how fast force grows when joystick move to the respective side */
+ int16_t right_coeff;
+ int16_t left_coeff;
+
+ uint16_t deadband; /* size of dead zone when no force is produced */
+ int16_t center; /* center of dead zone */
+};
+
+/*
+ * Force feedback periodic effect types
+ */
+
+#define FF_SQUARE 0x58
+#define FF_TRIANGLE 0x59
+#define FF_SINE 0x5a
+#define FF_SAW_UP 0x5b
+#define FF_SAW_DOWN 0x5c
+#define FF_CUSTOM 0x5d
+
+#define FF_WAVEFORM_MIN FF_SQUARE
+#define FF_WAVEFORM_MAX FF_CUSTOM
+
+struct ff_periodic_effect {
+ uint16_t waveform;
+ uint16_t period; /* ms */
+ int16_t magnitude; /* peak */
+ int16_t offset; /* mean, roughly */
+ uint16_t phase; /* horizontal shift */
+ struct ff_envelope envelope;
+ uint32_t custom_len; /* FF_CUSTOM waveform only */
+ int16_t *custom_data; /* FF_CUSTOM waveform only */
+};
+
+struct ff_rumble_effect {
+ uint16_t strong_magnitude; /* magnitude of the heavy motor */
+ uint16_t weak_magnitude; /* magnitude of the light motor */
+};
+
+/*
+ * Force feedback effect types
+ */
+
+#define FF_RUMBLE 0x50
+#define FF_PERIODIC 0x51
+#define FF_CONSTANT 0x52
+#define FF_SPRING 0x53
+#define FF_FRICTION 0x54
+#define FF_DAMPER 0x55
+#define FF_INERTIA 0x56
+#define FF_RAMP 0x57
+
+#define FF_EFFECT_MIN FF_RUMBLE
+#define FF_EFFECT_MAX FF_RAMP
+
+struct ff_effect {
+ uint16_t type;
+ int16_t id;
+ uint16_t direction; /* [0 .. 360) degrees -> [0 .. 0x10000) */
+ struct ff_trigger trigger;
+ struct ff_replay replay;
+
+ union {
+ struct ff_constant_effect constant;
+ struct ff_ramp_effect ramp;
+ struct ff_periodic_effect periodic;
+ struct ff_condition_effect condition[2]; /* One for each axis */
+ struct ff_rumble_effect rumble;
+ } u;
+};
+
+/*
+ * force feedback device properties
+ */
+
+#define FF_GAIN 0x60
+#define FF_AUTOCENTER 0x61
+
+#define FF_MAX 0x7f
+#define FF_CNT (FF_MAX+1)
+
+#endif /* _EVDEV_INPUT_H */
diff --git a/sys/dev/evdev/uinput.c b/sys/dev/evdev/uinput.c
new file mode 100644
index 0000000..77810b7
--- /dev/null
+++ b/sys/dev/evdev/uinput.c
@@ -0,0 +1,712 @@
+/*-
+ * Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
+ * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
+ * 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$
+ */
+
+#include "opt_evdev.h"
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/proc.h>
+#include <sys/poll.h>
+#include <sys/selinfo.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/sx.h>
+
+#include <dev/evdev/input.h>
+#include <dev/evdev/uinput.h>
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/evdev_private.h>
+
+#ifdef UINPUT_DEBUG
+#define debugf(state, fmt, args...) printf("uinput: " fmt "\n", ##args)
+#else
+#define debugf(state, fmt, args...)
+#endif
+
+#define UINPUT_BUFFER_SIZE 16
+
+#define UINPUT_LOCK(state) sx_xlock(&(state)->ucs_lock)
+#define UINPUT_UNLOCK(state) sx_unlock(&(state)->ucs_lock)
+#define UINPUT_LOCK_ASSERT(state) sx_assert(&(state)->ucs_lock, SA_LOCKED)
+#define UINPUT_EMPTYQ(state) \
+ ((state)->ucs_buffer_head == (state)->ucs_buffer_tail)
+
+enum uinput_state
+{
+ UINPUT_NEW = 0,
+ UINPUT_CONFIGURED,
+ UINPUT_RUNNING
+};
+
+static evdev_event_t uinput_ev_event;
+
+static d_open_t uinput_open;
+static d_read_t uinput_read;
+static d_write_t uinput_write;
+static d_ioctl_t uinput_ioctl;
+static d_poll_t uinput_poll;
+static d_kqfilter_t uinput_kqfilter;
+static void uinput_dtor(void *);
+
+static int uinput_kqread(struct knote *kn, long hint);
+static void uinput_kqdetach(struct knote *kn);
+
+static struct cdevsw uinput_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = uinput_open,
+ .d_read = uinput_read,
+ .d_write = uinput_write,
+ .d_ioctl = uinput_ioctl,
+ .d_poll = uinput_poll,
+ .d_kqfilter = uinput_kqfilter,
+ .d_name = "uinput",
+};
+
+static struct cdev *uinput_cdev;
+
+static struct evdev_methods uinput_ev_methods = {
+ .ev_open = NULL,
+ .ev_close = NULL,
+ .ev_event = uinput_ev_event,
+};
+
+static struct filterops uinput_filterops = {
+ .f_isfd = 1,
+ .f_attach = NULL,
+ .f_detach = uinput_kqdetach,
+ .f_event = uinput_kqread,
+};
+
+struct uinput_cdev_state
+{
+ enum uinput_state ucs_state;
+ struct evdev_dev * ucs_evdev;
+ struct sx ucs_lock;
+ size_t ucs_buffer_head;
+ size_t ucs_buffer_tail;
+ struct selinfo ucs_selp;
+ bool ucs_blocked;
+ bool ucs_selected;
+ struct input_event ucs_buffer[UINPUT_BUFFER_SIZE];
+};
+
+static void uinput_enqueue_event(struct uinput_cdev_state *, uint16_t,
+ uint16_t, int32_t);
+static int uinput_setup_provider(struct uinput_cdev_state *,
+ struct uinput_user_dev *);
+static int uinput_cdev_create(void);
+static void uinput_notify(struct uinput_cdev_state *);
+
+static void
+uinput_knllock(void *arg)
+{
+ struct sx *sx = arg;
+
+ sx_xlock(sx);
+}
+
+static void
+uinput_knlunlock(void *arg)
+{
+ struct sx *sx = arg;
+
+ sx_unlock(sx);
+}
+
+static void
+uinput_knl_assert_locked(void *arg)
+{
+
+ sx_assert((struct sx*)arg, SA_XLOCKED);
+}
+
+static void
+uinput_knl_assert_unlocked(void *arg)
+{
+
+ sx_assert((struct sx*)arg, SA_UNLOCKED);
+}
+
+static void
+uinput_ev_event(struct evdev_dev *evdev, void *softc, uint16_t type,
+ uint16_t code, int32_t value)
+{
+ struct uinput_cdev_state *state = softc;
+
+ if (type == EV_LED)
+ evdev_push_event(evdev, type, code, value);
+
+ UINPUT_LOCK(state);
+ if (state->ucs_state == UINPUT_RUNNING) {
+ uinput_enqueue_event(state, type, code, value);
+ uinput_notify(state);
+ }
+ UINPUT_UNLOCK(state);
+}
+
+static void
+uinput_enqueue_event(struct uinput_cdev_state *state, uint16_t type,
+ uint16_t code, int32_t value)
+{
+ size_t head, tail;
+
+ UINPUT_LOCK_ASSERT(state);
+
+ head = state->ucs_buffer_head;
+ tail = (state->ucs_buffer_tail + 1) % UINPUT_BUFFER_SIZE;
+
+ microtime(&state->ucs_buffer[tail].time);
+ state->ucs_buffer[tail].type = type;
+ state->ucs_buffer[tail].code = code;
+ state->ucs_buffer[tail].value = value;
+ state->ucs_buffer_tail = tail;
+
+ /* If queue is full remove oldest event */
+ if (tail == head) {
+ debugf(state, "state %p: buffer overflow", state);
+
+ head = (head + 1) % UINPUT_BUFFER_SIZE;
+ state->ucs_buffer_head = head;
+ }
+}
+
+static int
+uinput_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct uinput_cdev_state *state;
+
+ state = malloc(sizeof(struct uinput_cdev_state), M_EVDEV,
+ M_WAITOK | M_ZERO);
+ state->ucs_evdev = evdev_alloc();
+
+ sx_init(&state->ucs_lock, "uinput");
+ knlist_init(&state->ucs_selp.si_note, &state->ucs_lock, uinput_knllock,
+ uinput_knlunlock, uinput_knl_assert_locked,
+ uinput_knl_assert_unlocked);
+
+ devfs_set_cdevpriv(state, uinput_dtor);
+ return (0);
+}
+
+static void
+uinput_dtor(void *data)
+{
+ struct uinput_cdev_state *state = (struct uinput_cdev_state *)data;
+
+ evdev_free(state->ucs_evdev);
+
+ knlist_clear(&state->ucs_selp.si_note, 0);
+ seldrain(&state->ucs_selp);
+ knlist_destroy(&state->ucs_selp.si_note);
+ sx_destroy(&state->ucs_lock);
+ free(data, M_EVDEV);
+}
+
+static int
+uinput_read(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ struct uinput_cdev_state *state;
+ struct input_event *event;
+ int remaining, ret;
+
+ ret = devfs_get_cdevpriv((void **)&state);
+ if (ret != 0)
+ return (ret);
+
+ debugf(state, "read %zd bytes by thread %d", uio->uio_resid,
+ uio->uio_td->td_tid);
+
+ /* Zero-sized reads are allowed for error checking */
+ if (uio->uio_resid != 0 && uio->uio_resid < sizeof(struct input_event))
+ return (EINVAL);
+
+ remaining = uio->uio_resid / sizeof(struct input_event);
+
+ UINPUT_LOCK(state);
+
+ if (state->ucs_state != UINPUT_RUNNING)
+ ret = EINVAL;
+
+ if (ret == 0 && UINPUT_EMPTYQ(state)) {
+ if (ioflag & O_NONBLOCK)
+ ret = EWOULDBLOCK;
+ else {
+ if (remaining != 0) {
+ state->ucs_blocked = true;
+ ret = sx_sleep(state, &state->ucs_lock,
+ PCATCH, "uiread", 0);
+ }
+ }
+ }
+
+ while (ret == 0 && !UINPUT_EMPTYQ(state) && remaining > 0) {
+ event = &state->ucs_buffer[state->ucs_buffer_head];
+ state->ucs_buffer_head = (state->ucs_buffer_head + 1) %
+ UINPUT_BUFFER_SIZE;
+ remaining--;
+ ret = uiomove(event, sizeof(struct input_event), uio);
+ }
+
+ UINPUT_UNLOCK(state);
+
+ return (ret);
+}
+
+static int
+uinput_write(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ struct uinput_cdev_state *state;
+ struct uinput_user_dev userdev;
+ struct input_event event;
+ int ret = 0;
+
+ ret = devfs_get_cdevpriv((void **)&state);
+ if (ret != 0)
+ return (ret);
+
+ debugf(state, "write %zd bytes by thread %d", uio->uio_resid,
+ uio->uio_td->td_tid);
+
+ UINPUT_LOCK(state);
+
+ if (state->ucs_state != UINPUT_RUNNING) {
+ /* Process written struct uinput_user_dev */
+ if (uio->uio_resid != sizeof(struct uinput_user_dev)) {
+ debugf(state, "write size not multiple of "
+ "struct uinput_user_dev size");
+ ret = EINVAL;
+ } else {
+ ret = uiomove(&userdev, sizeof(struct uinput_user_dev),
+ uio);
+ if (ret == 0)
+ uinput_setup_provider(state, &userdev);
+ }
+ } else {
+ /* Process written event */
+ if (uio->uio_resid % sizeof(struct input_event) != 0) {
+ debugf(state, "write size not multiple of "
+ "struct input_event size");
+ ret = EINVAL;
+ }
+
+ while (ret == 0 && uio->uio_resid > 0) {
+ uiomove(&event, sizeof(struct input_event), uio);
+ ret = evdev_push_event(state->ucs_evdev, event.type,
+ event.code, event.value);
+ }
+ }
+
+ UINPUT_UNLOCK(state);
+
+ return (ret);
+}
+
+static int
+uinput_setup_dev(struct uinput_cdev_state *state, struct input_id *id,
+ char *name, uint32_t ff_effects_max)
+{
+
+ if (name[0] == 0)
+ return (EINVAL);
+
+ evdev_set_name(state->ucs_evdev, name);
+ evdev_set_id(state->ucs_evdev, id->bustype, id->vendor, id->product,
+ id->version);
+ state->ucs_state = UINPUT_CONFIGURED;
+
+ return (0);
+}
+
+static int
+uinput_setup_provider(struct uinput_cdev_state *state,
+ struct uinput_user_dev *udev)
+{
+ struct input_absinfo absinfo;
+ int i, ret;
+
+ debugf(state, "setup_provider called, udev=%p", udev);
+
+ ret = uinput_setup_dev(state, &udev->id, udev->name,
+ udev->ff_effects_max);
+ if (ret)
+ return (ret);
+
+ bzero(&absinfo, sizeof(struct input_absinfo));
+ for (i = 0; i < ABS_CNT; i++) {
+ if (!bit_test(state->ucs_evdev->ev_abs_flags, i))
+ continue;
+
+ absinfo.minimum = udev->absmin[i];
+ absinfo.maximum = udev->absmax[i];
+ absinfo.fuzz = udev->absfuzz[i];
+ absinfo.flat = udev->absflat[i];
+ evdev_set_absinfo(state->ucs_evdev, i, &absinfo);
+ }
+
+ return (0);
+}
+
+static int
+uinput_poll(struct cdev *dev, int events, struct thread *td)
+{
+ struct uinput_cdev_state *state;
+ int revents = 0;
+
+ if (devfs_get_cdevpriv((void **)&state) != 0)
+ return (POLLNVAL);
+
+ debugf(state, "poll by thread %d", td->td_tid);
+
+ /* Always allow write */
+ if (events & (POLLOUT | POLLWRNORM))
+ revents |= (events & (POLLOUT | POLLWRNORM));
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ UINPUT_LOCK(state);
+ if (!UINPUT_EMPTYQ(state))
+ revents = events & (POLLIN | POLLRDNORM);
+ else {
+ state->ucs_selected = true;
+ selrecord(td, &state->ucs_selp);
+ }
+ UINPUT_UNLOCK(state);
+ }
+
+ return (revents);
+}
+
+static int
+uinput_kqfilter(struct cdev *dev, struct knote *kn)
+{
+ struct uinput_cdev_state *state;
+ int ret;
+
+ ret = devfs_get_cdevpriv((void **)&state);
+ if (ret != 0)
+ return (ret);
+
+ switch(kn->kn_filter) {
+ case EVFILT_READ:
+ kn->kn_fop = &uinput_filterops;
+ break;
+ default:
+ return(EINVAL);
+ }
+ kn->kn_hook = (caddr_t)state;
+
+ knlist_add(&state->ucs_selp.si_note, kn, 0);
+ return (0);
+}
+
+static int
+uinput_kqread(struct knote *kn, long hint)
+{
+ struct uinput_cdev_state *state;
+ int ret;
+
+ state = (struct uinput_cdev_state *)kn->kn_hook;
+
+ UINPUT_LOCK_ASSERT(state);
+
+ ret = !UINPUT_EMPTYQ(state);
+ return (ret);
+}
+
+static void
+uinput_kqdetach(struct knote *kn)
+{
+ struct uinput_cdev_state *state;
+
+ state = (struct uinput_cdev_state *)kn->kn_hook;
+ knlist_remove(&state->ucs_selp.si_note, kn, 0);
+}
+
+static void
+uinput_notify(struct uinput_cdev_state *state)
+{
+
+ UINPUT_LOCK_ASSERT(state);
+
+ if (state->ucs_blocked) {
+ state->ucs_blocked = false;
+ wakeup(state);
+ }
+ if (state->ucs_selected) {
+ state->ucs_selected = false;
+ selwakeup(&state->ucs_selp);
+ }
+ KNOTE_LOCKED(&state->ucs_selp.si_note, 0);
+}
+
+static int
+uinput_ioctl_sub(struct uinput_cdev_state *state, u_long cmd, caddr_t data)
+{
+ struct uinput_setup *us;
+ struct uinput_abs_setup *uabs;
+ int ret, len, intdata;
+ char buf[NAMELEN];
+
+ UINPUT_LOCK_ASSERT(state);
+
+ len = IOCPARM_LEN(cmd);
+ if ((cmd & IOC_DIRMASK) == IOC_VOID && len == sizeof(int))
+ intdata = *(int *)data;
+
+ switch (IOCBASECMD(cmd)) {
+ case UI_GET_SYSNAME(0):
+ if (state->ucs_state != UINPUT_RUNNING)
+ return (ENOENT);
+ if (len == 0)
+ return (EINVAL);
+ snprintf(data, len, "event%d", state->ucs_evdev->ev_unit);
+ return (0);
+ }
+
+ switch (cmd) {
+ case UI_DEV_CREATE:
+ if (state->ucs_state != UINPUT_CONFIGURED)
+ return (EINVAL);
+
+ evdev_set_methods(state->ucs_evdev, state, &uinput_ev_methods);
+ evdev_set_flag(state->ucs_evdev, EVDEV_FLAG_SOFTREPEAT);
+ evdev_register(state->ucs_evdev);
+ state->ucs_state = UINPUT_RUNNING;
+ return (0);
+
+ case UI_DEV_DESTROY:
+ if (state->ucs_state != UINPUT_RUNNING)
+ return (0);
+
+ evdev_unregister(state->ucs_evdev);
+ bzero(state->ucs_evdev, sizeof(struct evdev_dev));
+ state->ucs_state = UINPUT_NEW;
+ return (0);
+
+ case UI_DEV_SETUP:
+ if (state->ucs_state == UINPUT_RUNNING)
+ return (EINVAL);
+
+ us = (struct uinput_setup *)data;
+ return (uinput_setup_dev(state, &us->id, us->name,
+ us->ff_effects_max));
+
+ case UI_ABS_SETUP:
+ if (state->ucs_state == UINPUT_RUNNING)
+ return (EINVAL);
+
+ uabs = (struct uinput_abs_setup *)data;
+ if (uabs->code > ABS_MAX)
+ return (EINVAL);
+
+ evdev_support_abs(state->ucs_evdev, uabs->code,
+ uabs->absinfo.value, uabs->absinfo.minimum,
+ uabs->absinfo.maximum, uabs->absinfo.fuzz,
+ uabs->absinfo.flat, uabs->absinfo.resolution);
+ return (0);
+
+ case UI_SET_EVBIT:
+ if (state->ucs_state == UINPUT_RUNNING ||
+ intdata > EV_MAX || intdata < 0)
+ return (EINVAL);
+ evdev_support_event(state->ucs_evdev, intdata);
+ return (0);
+
+ case UI_SET_KEYBIT:
+ if (state->ucs_state == UINPUT_RUNNING ||
+ intdata > KEY_MAX || intdata < 0)
+ return (EINVAL);
+ evdev_support_key(state->ucs_evdev, intdata);
+ return (0);
+
+ case UI_SET_RELBIT:
+ if (state->ucs_state == UINPUT_RUNNING ||
+ intdata > REL_MAX || intdata < 0)
+ return (EINVAL);
+ evdev_support_rel(state->ucs_evdev, intdata);
+ return (0);
+
+ case UI_SET_ABSBIT:
+ if (state->ucs_state == UINPUT_RUNNING ||
+ intdata > ABS_MAX || intdata < 0)
+ return (EINVAL);
+ evdev_set_abs_bit(state->ucs_evdev, intdata);
+ return (0);
+
+ case UI_SET_MSCBIT:
+ if (state->ucs_state == UINPUT_RUNNING ||
+ intdata > MSC_MAX || intdata < 0)
+ return (EINVAL);
+ evdev_support_msc(state->ucs_evdev, intdata);
+ return (0);
+
+ case UI_SET_LEDBIT:
+ if (state->ucs_state == UINPUT_RUNNING ||
+ intdata > LED_MAX || intdata < 0)
+ return (EINVAL);
+ evdev_support_led(state->ucs_evdev, intdata);
+ return (0);
+
+ case UI_SET_SNDBIT:
+ if (state->ucs_state == UINPUT_RUNNING ||
+ intdata > SND_MAX || intdata < 0)
+ return (EINVAL);
+ evdev_support_snd(state->ucs_evdev, intdata);
+ return (0);
+
+ case UI_SET_FFBIT:
+ if (state->ucs_state == UINPUT_RUNNING ||
+ intdata > FF_MAX || intdata < 0)
+ return (EINVAL);
+ /* Fake unsupported ioctl */
+ return (0);
+
+ case UI_SET_PHYS:
+ if (state->ucs_state == UINPUT_RUNNING)
+ return (EINVAL);
+ ret = copyinstr(*(void **)data, buf, sizeof(buf), NULL);
+ /* Linux returns EINVAL when string does not fit the buffer */
+ if (ret == ENAMETOOLONG)
+ ret = EINVAL;
+ if (ret != 0)
+ return (ret);
+ evdev_set_phys(state->ucs_evdev, buf);
+ return (0);
+
+ case UI_SET_SWBIT:
+ if (state->ucs_state == UINPUT_RUNNING ||
+ intdata > SW_MAX || intdata < 0)
+ return (EINVAL);
+ evdev_support_sw(state->ucs_evdev, intdata);
+ return (0);
+
+ case UI_SET_PROPBIT:
+ if (state->ucs_state == UINPUT_RUNNING ||
+ intdata > INPUT_PROP_MAX || intdata < 0)
+ return (EINVAL);
+ evdev_support_prop(state->ucs_evdev, intdata);
+ return (0);
+
+ case UI_BEGIN_FF_UPLOAD:
+ case UI_END_FF_UPLOAD:
+ case UI_BEGIN_FF_ERASE:
+ case UI_END_FF_ERASE:
+ if (state->ucs_state == UINPUT_RUNNING)
+ return (EINVAL);
+ /* Fake unsupported ioctl */
+ return (0);
+
+ case UI_GET_VERSION:
+ *(unsigned int *)data = UINPUT_VERSION;
+ return (0);
+ }
+
+ return (EINVAL);
+}
+
+static int
+uinput_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
+ struct thread *td)
+{
+ struct uinput_cdev_state *state;
+ int ret;
+
+ ret = devfs_get_cdevpriv((void **)&state);
+ if (ret != 0)
+ return (ret);
+
+ debugf(state, "ioctl called: cmd=0x%08lx, data=%p", cmd, data);
+
+ UINPUT_LOCK(state);
+ ret = uinput_ioctl_sub(state, cmd, data);
+ UINPUT_UNLOCK(state);
+
+ return (ret);
+}
+
+static int
+uinput_cdev_create(void)
+{
+ struct make_dev_args mda;
+ int ret;
+
+ make_dev_args_init(&mda);
+ mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
+ mda.mda_devsw = &uinput_cdevsw;
+ mda.mda_uid = UID_ROOT;
+ mda.mda_gid = GID_WHEEL;
+ mda.mda_mode = 0600;
+
+ ret = make_dev_s(&mda, &uinput_cdev, "uinput");
+
+ return (ret);
+}
+
+static int
+uinput_cdev_destroy(void)
+{
+
+ destroy_dev(uinput_cdev);
+
+ return (0);
+}
+
+static int
+uinput_modevent(module_t mod __unused, int cmd, void *data)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case MOD_LOAD:
+ ret = uinput_cdev_create();
+ break;
+
+ case MOD_UNLOAD:
+ ret = uinput_cdev_destroy();
+ break;
+
+ case MOD_SHUTDOWN:
+ break;
+
+ default:
+ ret = EINVAL;
+ break;
+ }
+
+ return (ret);
+}
+
+DEV_MODULE(uinput, uinput_modevent, NULL);
+MODULE_VERSION(uinput, 1);
+MODULE_DEPEND(uinput, evdev, 1, 1, 1);
diff --git a/sys/dev/evdev/uinput.h b/sys/dev/evdev/uinput.h
new file mode 100644
index 0000000..f1721e1
--- /dev/null
+++ b/sys/dev/evdev/uinput.h
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
+ * 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 _EVDEV_UINPUT_H_
+#define _EVDEV_UINPUT_H_
+
+#include <sys/types.h>
+#include <dev/evdev/input.h>
+
+#define UINPUT_VERSION 5
+#define UINPUT_MAX_NAME_SIZE 80
+
+struct uinput_ff_upload {
+ uint32_t request_id;
+ int32_t retval;
+ struct ff_effect effect;
+ struct ff_effect old;
+};
+
+struct uinput_ff_erase {
+ uint32_t request_id;
+ int32_t retval;
+ uint32_t effect_id;
+};
+
+/* ioctl */
+#define UINPUT_IOCTL_BASE 'U'
+
+#define UI_DEV_CREATE _IO(UINPUT_IOCTL_BASE, 1)
+#define UI_DEV_DESTROY _IO(UINPUT_IOCTL_BASE, 2)
+
+struct uinput_setup {
+ struct input_id id;
+ char name[UINPUT_MAX_NAME_SIZE];
+ uint32_t ff_effects_max;
+};
+
+#define UI_DEV_SETUP _IOW(UINPUT_IOCTL_BASE, 3, struct uinput_setup)
+
+struct uinput_abs_setup {
+ uint16_t code; /* axis code */
+ struct input_absinfo absinfo;
+};
+
+#define UI_ABS_SETUP _IOW(UINPUT_IOCTL_BASE, 4, struct uinput_abs_setup)
+
+#define UI_GET_SYSNAME(len) _IOC(IOC_OUT, UINPUT_IOCTL_BASE, 44, len)
+#define UI_GET_VERSION _IOR(UINPUT_IOCTL_BASE, 45, unsigned int)
+
+#define UI_SET_EVBIT _IOWINT(UINPUT_IOCTL_BASE, 100)
+#define UI_SET_KEYBIT _IOWINT(UINPUT_IOCTL_BASE, 101)
+#define UI_SET_RELBIT _IOWINT(UINPUT_IOCTL_BASE, 102)
+#define UI_SET_ABSBIT _IOWINT(UINPUT_IOCTL_BASE, 103)
+#define UI_SET_MSCBIT _IOWINT(UINPUT_IOCTL_BASE, 104)
+#define UI_SET_LEDBIT _IOWINT(UINPUT_IOCTL_BASE, 105)
+#define UI_SET_SNDBIT _IOWINT(UINPUT_IOCTL_BASE, 106)
+#define UI_SET_FFBIT _IOWINT(UINPUT_IOCTL_BASE, 107)
+#define UI_SET_PHYS _IO(UINPUT_IOCTL_BASE, 108)
+#define UI_SET_SWBIT _IOWINT(UINPUT_IOCTL_BASE, 109)
+#define UI_SET_PROPBIT _IOWINT(UINPUT_IOCTL_BASE, 110)
+
+#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
+#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
+#define UI_BEGIN_FF_ERASE _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
+#define UI_END_FF_ERASE _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
+
+#define EV_UINPUT 0x0101
+#define UI_FF_UPLOAD 1
+#define UI_FF_ERASE 2
+
+struct uinput_user_dev {
+ char name[UINPUT_MAX_NAME_SIZE];
+ struct input_id id;
+ uint32_t ff_effects_max;
+ int32_t absmax[ABS_CNT];
+ int32_t absmin[ABS_CNT];
+ int32_t absfuzz[ABS_CNT];
+ int32_t absflat[ABS_CNT];
+};
+
+#endif /* _EVDEV_UINPUT_H_ */
diff --git a/sys/dev/netmap/if_em_netmap.h b/sys/dev/netmap/if_em_netmap.h
index 28f2dd4..1fe7563 100644
--- a/sys/dev/netmap/if_em_netmap.h
+++ b/sys/dev/netmap/if_em_netmap.h
@@ -277,9 +277,9 @@ em_netmap_rxsync(struct netmap_kring *kring, int flags)
if (addr == NETMAP_BUF_BASE(na)) /* bad buf */
goto ring_reset;
+ curr->read.buffer_addr = htole64(paddr);
if (slot->flags & NS_BUF_CHANGED) {
/* buffer has changed, reload map */
- curr->read.buffer_addr = htole64(paddr);
netmap_reload_map(na, rxr->rxtag, rxbuf->map, addr);
slot->flags &= ~NS_BUF_CHANGED;
}
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 5bc938b..42d7d7c 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -4607,6 +4607,9 @@ static const struct
{PCIC_CRYPTO, PCIS_CRYPTO_ENTERTAIN, 1, "entertainment crypto"},
{PCIC_DASP, -1, 0, "dasp"},
{PCIC_DASP, PCIS_DASP_DPIO, 1, "DPIO module"},
+ {PCIC_DASP, PCIS_DASP_PERFCNTRS, 1, "performance counters"},
+ {PCIC_DASP, PCIS_DASP_COMM_SYNC, 1, "communication synchronizer"},
+ {PCIC_DASP, PCIS_DASP_MGMT_CARD, 1, "signal processing management"},
{0, 0, 0, NULL}
};
diff --git a/sys/dev/smbus/smbconf.h b/sys/dev/smbus/smbconf.h
index f39c442..2c120c1 100644
--- a/sys/dev/smbus/smbconf.h
+++ b/sys/dev/smbus/smbconf.h
@@ -34,6 +34,10 @@
#define n(flags) (~(flags) & (flags))
+/* Order constants for smbus children. */
+#define SMBUS_ORDER_HINTED 20
+#define SMBUS_ORDER_PNP 40
+
/*
* How tsleep() is called in smb_request_bus().
*/
diff --git a/sys/dev/smbus/smbus.c b/sys/dev/smbus/smbus.c
index 389efac..d485094 100644
--- a/sys/dev/smbus/smbus.c
+++ b/sys/dev/smbus/smbus.c
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/bus.h>
@@ -41,54 +42,16 @@ __FBSDID("$FreeBSD$");
#include "smbus_if.h"
#include "bus_if.h"
+struct smbus_ivar
+{
+ uint8_t addr;
+};
/*
* Autoconfiguration and support routines for System Management bus
*/
+static void smbus_probe_device(device_t dev, u_char addr);
-/*
- * Device methods
- */
-static int smbus_probe(device_t);
-static int smbus_attach(device_t);
-static int smbus_detach(device_t);
-
-static int smbus_child_location_str(device_t parent, device_t child,
- char *buf, size_t buflen);
-static int smbus_print_child(device_t parent, device_t child);
-static void smbus_probe_device(device_t dev, u_char* addr);
-static int smbus_read_ivar(device_t parent, device_t child, int which,
- uintptr_t *result);
-
-static device_method_t smbus_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, smbus_probe),
- DEVMETHOD(device_attach, smbus_attach),
- DEVMETHOD(device_detach, smbus_detach),
-
- /* bus interface */
- DEVMETHOD(bus_add_child, bus_generic_add_child),
- DEVMETHOD(bus_child_location_str, smbus_child_location_str),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
- DEVMETHOD(bus_print_child, smbus_print_child),
- DEVMETHOD(bus_read_ivar, smbus_read_ivar),
-
- DEVMETHOD_END
-};
-
-driver_t smbus_driver = {
- "smbus",
- smbus_methods,
- sizeof(struct smbus_softc),
-};
-
-devclass_t smbus_devclass;
-
-/*
- * At 'probe' time, we add all the devices which we know about to the
- * bus. The generic attach routine will probe and attach them if they
- * are alive.
- */
static int
smbus_probe(device_t dev)
{
@@ -107,9 +70,9 @@ smbus_attach(device_t dev)
mtx_init(&sc->lock, device_get_nameunit(dev), "smbus", MTX_DEF);
bus_generic_probe(dev);
for (addr = SMBUS_ADDR_MIN; addr < SMBUS_ADDR_MAX; ++addr) {
- sc->addrs[addr] = addr;
- smbus_probe_device(dev, &sc->addrs[addr]);
+ smbus_probe_device(dev, addr);
}
+ bus_enumerate_hinted_children(dev);
bus_generic_attach(dev);
return (0);
@@ -124,6 +87,7 @@ smbus_detach(device_t dev)
error = bus_generic_detach(dev);
if (error)
return (error);
+ device_delete_children(dev);
mtx_destroy(&sc->lock);
return (0);
@@ -135,34 +99,78 @@ smbus_generic_intr(device_t dev, u_char devaddr, char low, char high, int err)
}
static void
-smbus_probe_device(device_t dev, u_char* addr)
+smbus_probe_device(device_t dev, u_char addr)
{
device_t child;
int error;
u_char cmd;
u_char buf[2];
+ struct smbus_ivar *devi;
cmd = 0x01;
- error = smbus_trans(dev, *addr, cmd,
+ error = smbus_trans(dev, addr, cmd,
SMB_TRANS_NOCNT | SMB_TRANS_NOREPORT,
NULL, 0, buf, 1, NULL);
if (error == 0) {
if (bootverbose)
- device_printf(dev, "Probed address 0x%02x\n", *addr);
- child = device_add_child(dev, NULL, -1);
- device_set_ivars(child, addr);
+ device_printf(dev, "Probed address 0x%02x\n", addr);
+ child = BUS_ADD_CHILD(dev, SMBUS_ORDER_PNP, NULL, -1);
+ if (child == NULL)
+ return;
+ devi = device_get_ivars(child);
+ devi->addr = addr;
+ }
+}
+
+static device_t
+smbus_add_child(device_t dev, u_int order, const char *name, int unit)
+{
+ struct smbus_ivar *devi;
+ device_t child;
+
+ child = device_add_child_ordered(dev, order, name, unit);
+ if (child == NULL)
+ return (child);
+ devi = malloc(sizeof(struct smbus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (devi == NULL) {
+ device_delete_child(dev, child);
+ return (NULL);
+ }
+ device_set_ivars(child, devi);
+ return (child);
+}
+
+static void
+smbus_hinted_child(device_t bus, const char *dname, int dunit)
+{
+ struct smbus_ivar *devi;
+ device_t child;
+ int addr;
+
+ addr = 0;
+ resource_int_value(dname, dunit, "addr", &addr);
+ if (addr > UINT8_MAX) {
+ device_printf(bus, "ignored incorrect slave address hint 0x%x"
+ " for %s%d\n", addr, dname, dunit);
+ return;
}
+ child = BUS_ADD_CHILD(bus, SMBUS_ORDER_HINTED, dname, dunit);
+ if (child == NULL)
+ return;
+ devi = device_get_ivars(child);
+ devi->addr = addr;
}
+
static int
smbus_child_location_str(device_t parent, device_t child, char *buf,
size_t buflen)
{
- unsigned char *addr;
+ struct smbus_ivar *devi;
- addr = device_get_ivars(child);
- if (addr)
- snprintf(buf, buflen, "addr=0x%x", *addr);
+ devi = device_get_ivars(child);
+ if (devi->addr != 0)
+ snprintf(buf, buflen, "addr=0x%x", devi->addr);
else if (buflen)
buf[0] = 0;
return (0);
@@ -171,28 +179,30 @@ smbus_child_location_str(device_t parent, device_t child, char *buf,
static int
smbus_print_child(device_t parent, device_t child)
{
- unsigned char *addr;
+ struct smbus_ivar *devi;
int retval;
- addr = device_get_ivars(child);
+ devi = device_get_ivars(child);
retval = bus_print_child_header(parent, child);
- if (addr)
- retval += printf(" at addr 0x%x", *addr);
+ if (devi->addr != 0)
+ retval += printf(" at addr 0x%x", devi->addr);
retval += bus_print_child_footer(parent, child);
return (retval);
}
static int
-smbus_read_ivar(device_t parent, device_t child, int which,
- uintptr_t *result)
+smbus_read_ivar(device_t parent, device_t child, int which, uintptr_t *result)
{
- unsigned char *addr;
+ struct smbus_ivar *devi;
- addr = device_get_ivars(child);
+ devi = device_get_ivars(child);
switch (which) {
case SMBUS_IVAR_ADDR:
- *result = (addr == NULL) ? -1 : *addr;
+ if (devi->addr != 0)
+ *result = devi->addr;
+ else
+ *result = -1;
break;
default:
return (ENOENT);
@@ -200,4 +210,66 @@ smbus_read_ivar(device_t parent, device_t child, int which,
return (0);
}
+static int
+smbus_write_ivar(device_t parent, device_t child, int which, uintptr_t value)
+{
+ struct smbus_ivar *devi;
+
+ devi = device_get_ivars(child);
+ switch (which) {
+ case SMBUS_IVAR_ADDR:
+ /* Allow to set but no change the slave address. */
+ if (devi->addr != 0)
+ return (EINVAL);
+ devi->addr = value;
+ break;
+ default:
+ return (ENOENT);
+ }
+ return (0);
+}
+
+static void
+smbus_probe_nomatch(device_t bus, device_t child)
+{
+ struct smbus_ivar *devi = device_get_ivars(child);
+
+ /*
+ * Ignore (self-identified) devices without a slave address set.
+ * For example, smb(4).
+ */
+ if (devi->addr != 0)
+ device_printf(bus, "<unknown device> at addr %#x\n",
+ devi->addr);
+}
+
+/*
+ * Device methods
+ */
+static device_method_t smbus_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, smbus_probe),
+ DEVMETHOD(device_attach, smbus_attach),
+ DEVMETHOD(device_detach, smbus_detach),
+
+ /* bus interface */
+ DEVMETHOD(bus_add_child, smbus_add_child),
+ DEVMETHOD(bus_hinted_child, smbus_hinted_child),
+ DEVMETHOD(bus_probe_nomatch, smbus_probe_nomatch),
+ DEVMETHOD(bus_child_location_str, smbus_child_location_str),
+ DEVMETHOD(bus_print_child, smbus_print_child),
+ DEVMETHOD(bus_read_ivar, smbus_read_ivar),
+ DEVMETHOD(bus_write_ivar, smbus_write_ivar),
+
+ DEVMETHOD_END
+};
+
+driver_t smbus_driver = {
+ "smbus",
+ smbus_methods,
+ sizeof(struct smbus_softc),
+};
+
+devclass_t smbus_devclass;
+
MODULE_VERSION(smbus, SMBUS_MODVER);
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index 3de87ae..7e32b70 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -95,6 +95,7 @@ __FBSDID("$FreeBSD$");
static int uaudio_default_rate = 0; /* use rate list */
static int uaudio_default_bits = 32;
static int uaudio_default_channels = 0; /* use default */
+static int uaudio_buffer_ms = 8;
#ifdef USB_DEBUG
static int uaudio_debug = 0;
@@ -109,9 +110,32 @@ SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, default_bits, CTLFLAG_RWTUN,
&uaudio_default_bits, 0, "uaudio default sample bits");
SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, default_channels, CTLFLAG_RWTUN,
&uaudio_default_channels, 0, "uaudio default sample channels");
+
+static int
+uaudio_buffer_ms_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ int err, val;
+
+ val = uaudio_buffer_ms;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err != 0 || req->newptr == NULL || val == uaudio_buffer_ms)
+ return (err);
+
+ if (val > 8)
+ val = 8;
+ else if (val < 2)
+ val = 2;
+
+ uaudio_buffer_ms = val;
+
+ return (0);
+}
+SYSCTL_PROC(_hw_usb_uaudio, OID_AUTO, buffer_ms, CTLTYPE_INT | CTLFLAG_RWTUN,
+ 0, sizeof(int), uaudio_buffer_ms_sysctl, "I",
+ "uaudio buffering delay from 2ms to 8ms");
#endif
-#define UAUDIO_IRQS (8000 / UAUDIO_NFRAMES) /* interrupts per second */
#define UAUDIO_NFRAMES 64 /* must be factor of 8 due HS-USB */
#define UAUDIO_NCHANBUFS 2 /* number of outstanding request */
#define UAUDIO_RECURSE_LIMIT 255 /* rounds */
@@ -1278,10 +1302,10 @@ uaudio_configure_msg_sub(struct uaudio_softc *sc,
if (fps < 8000) {
/* FULL speed USB */
- frames = 8;
+ frames = uaudio_buffer_ms;
} else {
/* HIGH speed USB */
- frames = UAUDIO_NFRAMES;
+ frames = uaudio_buffer_ms * 8;
}
fps_shift = usbd_xfer_get_fps_shift(chan->xfer[0]);
@@ -2158,8 +2182,9 @@ tr_setup:
}
/* start the SYNC transfer one time per second, if any */
- if (++(ch->intr_counter) >= UAUDIO_IRQS) {
- ch->intr_counter = 0;
+ ch->intr_counter += ch->intr_frames;
+ if (ch->intr_counter >= ch->frames_per_second) {
+ ch->intr_counter -= ch->frames_per_second;
usbd_transfer_start(ch->xfer[UAUDIO_NCHANBUFS]);
}
diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
index 6cc2f75..f6d16f3 100644
--- a/sys/dev/usb/input/ukbd.c
+++ b/sys/dev/usb/input/ukbd.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include "opt_compat.h"
#include "opt_kbd.h"
#include "opt_ukbd.h"
+#include "opt_evdev.h"
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -73,6 +74,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/quirk/usb_quirk.h>
+#ifdef EVDEV_SUPPORT
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+#endif
+
#include <sys/ioccom.h>
#include <sys/filio.h>
#include <sys/tty.h>
@@ -162,6 +168,9 @@ struct ukbd_softc {
struct usb_device *sc_udev;
struct usb_interface *sc_iface;
struct usb_xfer *sc_xfer[UKBD_N_TRANSFER];
+#ifdef EVDEV_SUPPORT
+ struct evdev_dev *sc_evdev;
+#endif
uint32_t sc_ntime[UKBD_NKEYCODE];
uint32_t sc_otime[UKBD_NKEYCODE];
@@ -377,6 +386,12 @@ static device_attach_t ukbd_attach;
static device_detach_t ukbd_detach;
static device_resume_t ukbd_resume;
+#ifdef EVDEV_SUPPORT
+static const struct evdev_methods ukbd_evdev_methods = {
+ .ev_event = evdev_ev_kbd_event,
+};
+#endif
+
static uint8_t
ukbd_any_key_pressed(struct ukbd_softc *sc)
{
@@ -405,6 +420,14 @@ ukbd_put_key(struct ukbd_softc *sc, uint32_t key)
DPRINTF("0x%02x (%d) %s\n", key, key,
(key & KEY_RELEASE) ? "released" : "pressed");
+#ifdef EVDEV_SUPPORT
+ if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD && sc->sc_evdev != NULL) {
+ evdev_push_event(sc->sc_evdev, EV_KEY,
+ evdev_hid2key(KEY_INDEX(key)), !(key & KEY_RELEASE));
+ evdev_sync(sc->sc_evdev);
+ }
+#endif
+
if (sc->sc_inputs < UKBD_IN_BUF_SIZE) {
sc->sc_input[sc->sc_inputtail] = key;
++(sc->sc_inputs);
@@ -918,6 +941,11 @@ ukbd_set_leds_callback(struct usb_xfer *xfer, usb_error_t error)
if (!any)
break;
+#ifdef EVDEV_SUPPORT
+ if (sc->sc_evdev != NULL)
+ evdev_push_leds(sc->sc_evdev, sc->sc_leds);
+#endif
+
/* range check output report length */
len = sc->sc_led_size;
if (len > (UKBD_BUFFER_SIZE - 1))
@@ -1193,6 +1221,10 @@ ukbd_attach(device_t dev)
usb_error_t err;
uint16_t n;
uint16_t hid_len;
+#ifdef EVDEV_SUPPORT
+ struct evdev_dev *evdev;
+ int i;
+#endif
#ifdef USB_DEBUG
int rate;
#endif
@@ -1307,6 +1339,37 @@ ukbd_attach(device_t dev)
goto detach;
}
#endif
+
+#ifdef EVDEV_SUPPORT
+ evdev = evdev_alloc();
+ evdev_set_name(evdev, device_get_desc(dev));
+ evdev_set_phys(evdev, device_get_nameunit(dev));
+ evdev_set_id(evdev, BUS_USB, uaa->info.idVendor,
+ uaa->info.idProduct, 0);
+ evdev_set_serial(evdev, usb_get_serial(uaa->device));
+ evdev_set_methods(evdev, kbd, &ukbd_evdev_methods);
+ evdev_support_event(evdev, EV_SYN);
+ evdev_support_event(evdev, EV_KEY);
+ if (sc->sc_flags & (UKBD_FLAG_NUMLOCK | UKBD_FLAG_CAPSLOCK |
+ UKBD_FLAG_SCROLLLOCK))
+ evdev_support_event(evdev, EV_LED);
+ evdev_support_event(evdev, EV_REP);
+
+ for (i = 0x00; i <= 0xFF; i++)
+ evdev_support_key(evdev, evdev_hid2key(i));
+ if (sc->sc_flags & UKBD_FLAG_NUMLOCK)
+ evdev_support_led(evdev, LED_NUML);
+ if (sc->sc_flags & UKBD_FLAG_CAPSLOCK)
+ evdev_support_led(evdev, LED_CAPSL);
+ if (sc->sc_flags & UKBD_FLAG_SCROLLLOCK)
+ evdev_support_led(evdev, LED_SCROLLL);
+
+ if (evdev_register(evdev))
+ evdev_free(evdev);
+ else
+ sc->sc_evdev = evdev;
+#endif
+
sc->sc_flags |= UKBD_FLAG_ATTACHED;
if (bootverbose) {
@@ -1377,6 +1440,11 @@ ukbd_detach(device_t dev)
}
}
#endif
+
+#ifdef EVDEV_SUPPORT
+ evdev_free(sc->sc_evdev);
+#endif
+
if (KBD_IS_CONFIGURED(&sc->sc_kbd)) {
error = kbd_unregister(&sc->sc_kbd);
if (error) {
@@ -1908,6 +1976,10 @@ ukbd_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t arg)
else
kbd->kb_delay1 = ((int *)arg)[0];
kbd->kb_delay2 = ((int *)arg)[1];
+#ifdef EVDEV_SUPPORT
+ if (sc->sc_evdev != NULL)
+ evdev_push_repeats(sc->sc_evdev, kbd);
+#endif
return (0);
#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
@@ -2056,6 +2128,9 @@ ukbd_set_leds(struct ukbd_softc *sc, uint8_t leds)
static int
ukbd_set_typematic(keyboard_t *kbd, int code)
{
+#ifdef EVDEV_SUPPORT
+ struct ukbd_softc *sc = kbd->kb_data;
+#endif
static const int delays[] = {250, 500, 750, 1000};
static const int rates[] = {34, 38, 42, 46, 50, 55, 59, 63,
68, 76, 84, 92, 100, 110, 118, 126,
@@ -2067,6 +2142,10 @@ ukbd_set_typematic(keyboard_t *kbd, int code)
}
kbd->kb_delay1 = delays[(code >> 5) & 3];
kbd->kb_delay2 = rates[code & 0x1f];
+#ifdef EVDEV_SUPPORT
+ if (sc->sc_evdev != NULL)
+ evdev_push_repeats(sc->sc_evdev, kbd);
+#endif
return (0);
}
@@ -2218,5 +2297,8 @@ static driver_t ukbd_driver = {
DRIVER_MODULE(ukbd, uhub, ukbd_driver, ukbd_devclass, ukbd_driver_load, 0);
MODULE_DEPEND(ukbd, usb, 1, 1, 1);
+#ifdef EVDEV_SUPPORT
+MODULE_DEPEND(ukbd, evdev, 1, 1, 1);
+#endif
MODULE_VERSION(ukbd, 1);
USB_PNP_HOST_INFO(ukbd_devs);
diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c
index a26db87..4d60517 100644
--- a/sys/dev/usb/input/ums.c
+++ b/sys/dev/usb/input/ums.c
@@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
* HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
*/
+#include "opt_evdev.h"
+
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -68,6 +70,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/quirk/usb_quirk.h>
+#ifdef EVDEV_SUPPORT
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+#endif
+
#include <sys/ioccom.h>
#include <sys/filio.h>
#include <sys/tty.h>
@@ -135,10 +142,18 @@ struct ums_softc {
int sc_pollrate;
int sc_fflags;
+#ifdef EVDEV_SUPPORT
+ int sc_evflags;
+#define UMS_EVDEV_OPENED 1
+#endif
uint8_t sc_buttons;
uint8_t sc_iid;
uint8_t sc_temp[64];
+
+#ifdef EVDEV_SUPPORT
+ struct evdev_dev *sc_evdev;
+#endif
};
static void ums_put_queue_timeout(void *__sc);
@@ -149,25 +164,39 @@ static device_probe_t ums_probe;
static device_attach_t ums_attach;
static device_detach_t ums_detach;
-static usb_fifo_cmd_t ums_start_read;
-static usb_fifo_cmd_t ums_stop_read;
-static usb_fifo_open_t ums_open;
-static usb_fifo_close_t ums_close;
-static usb_fifo_ioctl_t ums_ioctl;
+static usb_fifo_cmd_t ums_fifo_start_read;
+static usb_fifo_cmd_t ums_fifo_stop_read;
+static usb_fifo_open_t ums_fifo_open;
+static usb_fifo_close_t ums_fifo_close;
+static usb_fifo_ioctl_t ums_fifo_ioctl;
+#ifdef EVDEV_SUPPORT
+static evdev_open_t ums_ev_open;
+static evdev_close_t ums_ev_close;
+#endif
+
+static void ums_start_rx(struct ums_softc *);
+static void ums_stop_rx(struct ums_softc *);
static void ums_put_queue(struct ums_softc *, int32_t, int32_t,
int32_t, int32_t, int32_t);
static int ums_sysctl_handler_parseinfo(SYSCTL_HANDLER_ARGS);
static struct usb_fifo_methods ums_fifo_methods = {
- .f_open = &ums_open,
- .f_close = &ums_close,
- .f_ioctl = &ums_ioctl,
- .f_start_read = &ums_start_read,
- .f_stop_read = &ums_stop_read,
+ .f_open = &ums_fifo_open,
+ .f_close = &ums_fifo_close,
+ .f_ioctl = &ums_fifo_ioctl,
+ .f_start_read = &ums_fifo_start_read,
+ .f_stop_read = &ums_fifo_stop_read,
.basename[0] = "ums",
};
+#ifdef EVDEV_SUPPORT
+static const struct evdev_methods ums_evdev_methods = {
+ .ev_open = &ums_ev_open,
+ .ev_close = &ums_ev_close,
+};
+#endif
+
static void
ums_put_queue_timeout(void *__sc)
{
@@ -327,11 +356,17 @@ ums_intr_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
tr_setup:
/* check if we can put more data into the FIFO */
- if (usb_fifo_put_bytes_max(
- sc->sc_fifo.fp[USB_FIFO_RX]) != 0) {
- usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
- usbd_transfer_submit(xfer);
+ if (usb_fifo_put_bytes_max(sc->sc_fifo.fp[USB_FIFO_RX]) == 0) {
+#ifdef EVDEV_SUPPORT
+ if (sc->sc_evflags == 0)
+ break;
+#else
+ break;
+#endif
}
+
+ usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+ usbd_transfer_submit(xfer);
break;
default: /* Error */
@@ -655,6 +690,41 @@ ums_attach(device_t dev)
if (err)
goto detach;
+#ifdef EVDEV_SUPPORT
+ sc->sc_evdev = evdev_alloc();
+ evdev_set_name(sc->sc_evdev, device_get_desc(dev));
+ evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
+ evdev_set_id(sc->sc_evdev, BUS_USB, uaa->info.idVendor,
+ uaa->info.idProduct, 0);
+ evdev_set_serial(sc->sc_evdev, usb_get_serial(uaa->device));
+ evdev_set_methods(sc->sc_evdev, sc, &ums_evdev_methods);
+ evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER);
+ evdev_support_event(sc->sc_evdev, EV_SYN);
+ evdev_support_event(sc->sc_evdev, EV_REL);
+ evdev_support_event(sc->sc_evdev, EV_KEY);
+
+ info = &sc->sc_info[0];
+
+ if (info->sc_flags & UMS_FLAG_X_AXIS)
+ evdev_support_rel(sc->sc_evdev, REL_X);
+
+ if (info->sc_flags & UMS_FLAG_Y_AXIS)
+ evdev_support_rel(sc->sc_evdev, REL_Y);
+
+ if (info->sc_flags & UMS_FLAG_Z_AXIS)
+ evdev_support_rel(sc->sc_evdev, REL_WHEEL);
+
+ if (info->sc_flags & UMS_FLAG_T_AXIS)
+ evdev_support_rel(sc->sc_evdev, REL_HWHEEL);
+
+ for (i = 0; i < info->sc_buttons; i++)
+ evdev_support_key(sc->sc_evdev, BTN_MOUSE + i);
+
+ err = evdev_register(sc->sc_evdev);
+ if (err)
+ goto detach;
+#endif
+
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
OID_AUTO, "parseinfo", CTLTYPE_STRING|CTLFLAG_RD,
@@ -680,6 +750,10 @@ ums_detach(device_t self)
usb_fifo_detach(&sc->sc_fifo);
+#ifdef EVDEV_SUPPORT
+ evdev_free(sc->sc_evdev);
+#endif
+
usbd_transfer_unsetup(sc->sc_xfer, UMS_N_TRANSFER);
usb_callout_drain(&sc->sc_callout);
@@ -690,9 +764,44 @@ ums_detach(device_t self)
}
static void
-ums_start_read(struct usb_fifo *fifo)
+ums_reset(struct ums_softc *sc)
+{
+
+ /* reset all USB mouse parameters */
+
+ if (sc->sc_buttons > MOUSE_MSC_MAXBUTTON)
+ sc->sc_hw.buttons = MOUSE_MSC_MAXBUTTON;
+ else
+ sc->sc_hw.buttons = sc->sc_buttons;
+
+ sc->sc_hw.iftype = MOUSE_IF_USB;
+ sc->sc_hw.type = MOUSE_MOUSE;
+ sc->sc_hw.model = MOUSE_MODEL_GENERIC;
+ sc->sc_hw.hwid = 0;
+
+ sc->sc_mode.protocol = MOUSE_PROTO_MSC;
+ sc->sc_mode.rate = -1;
+ sc->sc_mode.resolution = MOUSE_RES_UNKNOWN;
+ sc->sc_mode.accelfactor = 0;
+ sc->sc_mode.level = 0;
+ sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
+ sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
+ sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
+
+ /* reset status */
+
+ sc->sc_status.flags = 0;
+ sc->sc_status.button = 0;
+ sc->sc_status.obutton = 0;
+ sc->sc_status.dx = 0;
+ sc->sc_status.dy = 0;
+ sc->sc_status.dz = 0;
+ /* sc->sc_status.dt = 0; */
+}
+
+static void
+ums_start_rx(struct ums_softc *sc)
{
- struct ums_softc *sc = usb_fifo_softc(fifo);
int rate;
/* Check if we should override the default polling interval */
@@ -715,14 +824,28 @@ ums_start_read(struct usb_fifo *fifo)
}
static void
-ums_stop_read(struct usb_fifo *fifo)
+ums_stop_rx(struct ums_softc *sc)
{
- struct ums_softc *sc = usb_fifo_softc(fifo);
-
usbd_transfer_stop(sc->sc_xfer[UMS_INTR_DT]);
usb_callout_stop(&sc->sc_callout);
}
+static void
+ums_fifo_start_read(struct usb_fifo *fifo)
+{
+ struct ums_softc *sc = usb_fifo_softc(fifo);
+
+ ums_start_rx(sc);
+}
+
+static void
+ums_fifo_stop_read(struct usb_fifo *fifo)
+{
+ struct ums_softc *sc = usb_fifo_softc(fifo);
+
+ ums_stop_rx(sc);
+}
+
#if ((MOUSE_SYS_PACKETSIZE != 8) || \
(MOUSE_MSC_PACKETSIZE != 5))
@@ -769,6 +892,21 @@ ums_put_queue(struct ums_softc *sc, int32_t dx, int32_t dy,
usb_fifo_put_data_linear(sc->sc_fifo.fp[USB_FIFO_RX], buf,
sc->sc_mode.packetsize, 1);
+#ifdef EVDEV_SUPPORT
+ if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) {
+ /* Push evdev event */
+ evdev_push_event(sc->sc_evdev, EV_REL, REL_X, dx);
+ evdev_push_event(sc->sc_evdev, EV_REL, REL_Y, -dy);
+ evdev_push_event(sc->sc_evdev, EV_REL, REL_WHEEL, -dz);
+ evdev_push_event(sc->sc_evdev, EV_REL, REL_HWHEEL, dt);
+ evdev_push_mouse_btn(sc->sc_evdev,
+ (buttons & ~MOUSE_STDBUTTONS) |
+ (buttons & (1 << 2) ? MOUSE_BUTTON1DOWN : 0) |
+ (buttons & (1 << 1) ? MOUSE_BUTTON2DOWN : 0) |
+ (buttons & (1 << 0) ? MOUSE_BUTTON3DOWN : 0));
+ evdev_sync(sc->sc_evdev);
+ }
+#endif
} else {
DPRINTF("Buffer full, discarded packet\n");
}
@@ -781,8 +919,44 @@ ums_reset_buf(struct ums_softc *sc)
usb_fifo_reset(sc->sc_fifo.fp[USB_FIFO_RX]);
}
+#ifdef EVDEV_SUPPORT
+static int
+ums_ev_open(struct evdev_dev *evdev, void *ev_softc)
+{
+ struct ums_softc *sc = (struct ums_softc *)ev_softc;
+
+ mtx_lock(&sc->sc_mtx);
+
+ sc->sc_evflags = UMS_EVDEV_OPENED;
+
+ if (sc->sc_fflags == 0) {
+ ums_reset(sc);
+ ums_start_rx(sc);
+ }
+
+ mtx_unlock(&sc->sc_mtx);
+
+ return (0);
+}
+
+static void
+ums_ev_close(struct evdev_dev *evdev, void *ev_softc)
+{
+ struct ums_softc *sc = (struct ums_softc *)ev_softc;
+
+ mtx_lock(&sc->sc_mtx);
+
+ sc->sc_evflags = 0;
+
+ if (sc->sc_fflags == 0)
+ ums_stop_rx(sc);
+
+ mtx_unlock(&sc->sc_mtx);
+}
+#endif
+
static int
-ums_open(struct usb_fifo *fifo, int fflags)
+ums_fifo_open(struct usb_fifo *fifo, int fflags)
{
struct ums_softc *sc = usb_fifo_softc(fifo);
@@ -793,39 +967,13 @@ ums_open(struct usb_fifo *fifo, int fflags)
return (EBUSY);
/* check for first open */
- if (sc->sc_fflags == 0) {
-
- /* reset all USB mouse parameters */
-
- if (sc->sc_buttons > MOUSE_MSC_MAXBUTTON)
- sc->sc_hw.buttons = MOUSE_MSC_MAXBUTTON;
- else
- sc->sc_hw.buttons = sc->sc_buttons;
-
- sc->sc_hw.iftype = MOUSE_IF_USB;
- sc->sc_hw.type = MOUSE_MOUSE;
- sc->sc_hw.model = MOUSE_MODEL_GENERIC;
- sc->sc_hw.hwid = 0;
-
- sc->sc_mode.protocol = MOUSE_PROTO_MSC;
- sc->sc_mode.rate = -1;
- sc->sc_mode.resolution = MOUSE_RES_UNKNOWN;
- sc->sc_mode.accelfactor = 0;
- sc->sc_mode.level = 0;
- sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
- sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
- sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
-
- /* reset status */
-
- sc->sc_status.flags = 0;
- sc->sc_status.button = 0;
- sc->sc_status.obutton = 0;
- sc->sc_status.dx = 0;
- sc->sc_status.dy = 0;
- sc->sc_status.dz = 0;
- /* sc->sc_status.dt = 0; */
- }
+#ifdef EVDEV_SUPPORT
+ if (sc->sc_fflags == 0 && sc->sc_evflags == 0)
+ ums_reset(sc);
+#else
+ if (sc->sc_fflags == 0)
+ ums_reset(sc);
+#endif
if (fflags & FREAD) {
/* allocate RX buffer */
@@ -840,7 +988,7 @@ ums_open(struct usb_fifo *fifo, int fflags)
}
static void
-ums_close(struct usb_fifo *fifo, int fflags)
+ums_fifo_close(struct usb_fifo *fifo, int fflags)
{
struct ums_softc *sc = usb_fifo_softc(fifo);
@@ -853,7 +1001,7 @@ ums_close(struct usb_fifo *fifo, int fflags)
}
static int
-ums_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
+ums_fifo_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
{
struct ums_softc *sc = usb_fifo_softc(fifo);
mousemode_t mode;
@@ -1051,5 +1199,8 @@ static driver_t ums_driver = {
DRIVER_MODULE(ums, uhub, ums_driver, ums_devclass, NULL, 0);
MODULE_DEPEND(ums, usb, 1, 1, 1);
+#ifdef EVDEV_SUPPORT
+MODULE_DEPEND(ums, evdev, 1, 1, 1);
+#endif
MODULE_VERSION(ums, 1);
USB_PNP_HOST_INFO(ums_devs);
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index 63d60dd..9b42b20 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -175,24 +175,8 @@ update_mp(struct mount *mp, struct thread *td)
if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
- else if (!(pmp->pm_flags &
- (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) {
- struct vnode *rootvp;
-
- /*
- * Try to divine whether to support Win'95 long filenames
- */
- if (FAT32(pmp))
- pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
- else {
- if ((error =
- msdosfs_root(mp, LK_EXCLUSIVE, &rootvp)) != 0)
- return error;
- pmp->pm_flags |= findwin95(VTODE(rootvp)) ?
- MSDOSFSMNT_LONGNAME : MSDOSFSMNT_SHORTNAME;
- vput(rootvp);
- }
- }
+ else
+ pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
return 0;
}
diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c
index 0c48a94..50b9f94 100644
--- a/sys/geom/mirror/g_mirror.c
+++ b/sys/geom/mirror/g_mirror.c
@@ -99,7 +99,7 @@ struct g_class g_mirror_class = {
static void g_mirror_destroy_provider(struct g_mirror_softc *sc);
static int g_mirror_update_disk(struct g_mirror_disk *disk, u_int state);
-static void g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force);
+static void g_mirror_update_device(struct g_mirror_softc *sc, bool force);
static void g_mirror_dumpconf(struct sbuf *sb, const char *indent,
struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp);
static void g_mirror_sync_stop(struct g_mirror_disk *disk, int type);
@@ -1822,7 +1822,7 @@ g_mirror_worker(void *arg)
"Running event for device %s.",
sc->sc_name);
ep->e_error = 0;
- g_mirror_update_device(sc, 1);
+ g_mirror_update_device(sc, true);
} else {
/* Update disk status. */
G_MIRROR_DEBUG(3, "Running event for disk %s.",
@@ -1830,7 +1830,7 @@ g_mirror_worker(void *arg)
ep->e_error = g_mirror_update_disk(ep->e_disk,
ep->e_state);
if (ep->e_error == 0)
- g_mirror_update_device(sc, 0);
+ g_mirror_update_device(sc, false);
}
if ((ep->e_flags & G_MIRROR_EVENT_DONTWAIT) != 0) {
KASSERT(ep->e_error == 0,
@@ -2137,10 +2137,9 @@ g_mirror_destroy_provider(struct g_mirror_softc *sc)
}
}
mtx_unlock(&sc->sc_queue_mtx);
- G_MIRROR_DEBUG(0, "Device %s: provider %s destroyed.", sc->sc_name,
- sc->sc_provider->name);
g_wither_provider(sc->sc_provider, ENXIO);
sc->sc_provider = NULL;
+ G_MIRROR_DEBUG(0, "Device %s: provider destroyed.", sc->sc_name);
g_topology_unlock();
LIST_FOREACH(disk, &sc->sc_disks, d_next) {
if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING)
@@ -2228,7 +2227,7 @@ g_mirror_determine_state(struct g_mirror_disk *disk)
* Update device state.
*/
static void
-g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force)
+g_mirror_update_device(struct g_mirror_softc *sc, bool force)
{
struct g_mirror_disk *disk;
u_int state;
@@ -2866,7 +2865,7 @@ static int
g_mirror_access(struct g_provider *pp, int acr, int acw, int ace)
{
struct g_mirror_softc *sc;
- int dcr, dcw, dce, error = 0;
+ int error = 0;
g_topology_assert();
G_MIRROR_DEBUG(2, "Access request for %s: r%dw%de%d.", pp->name, acr,
@@ -2877,30 +2876,21 @@ g_mirror_access(struct g_provider *pp, int acr, int acw, int ace)
return (0);
KASSERT(sc != NULL, ("NULL softc (provider=%s).", pp->name));
- dcr = pp->acr + acr;
- dcw = pp->acw + acw;
- dce = pp->ace + ace;
-
g_topology_unlock();
sx_xlock(&sc->sc_lock);
if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0 ||
+ (sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0 ||
LIST_EMPTY(&sc->sc_disks)) {
if (acr > 0 || acw > 0 || ace > 0)
error = ENXIO;
goto end;
}
- if (dcw == 0)
- g_mirror_idle(sc, dcw);
- if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0) {
- if (acr > 0 || acw > 0 || ace > 0) {
- error = ENXIO;
- goto end;
- }
- if (dcr == 0 && dcw == 0 && dce == 0) {
- g_post_event(g_mirror_destroy_delayed, sc, M_WAITOK,
- sc, NULL);
- }
- }
+ sc->sc_provider_open += acr + acw + ace;
+ if (pp->acw + acw == 0)
+ g_mirror_idle(sc, 0);
+ if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0 &&
+ sc->sc_provider_open == 0)
+ g_post_event(g_mirror_destroy_delayed, sc, M_WAITOK, sc, NULL);
end:
sx_xunlock(&sc->sc_lock);
g_topology_lock();
@@ -2957,6 +2947,7 @@ g_mirror_create(struct g_class *mp, const struct g_mirror_metadata *md)
gp->softc = sc;
sc->sc_geom = gp;
sc->sc_provider = NULL;
+ sc->sc_provider_open = 0;
/*
* Synchronization geom.
*/
@@ -2997,26 +2988,23 @@ int
g_mirror_destroy(struct g_mirror_softc *sc, int how)
{
struct g_mirror_disk *disk;
- struct g_provider *pp;
g_topology_assert_not();
if (sc == NULL)
return (ENXIO);
sx_assert(&sc->sc_lock, SX_XLOCKED);
- pp = sc->sc_provider;
- if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0 ||
- SCHEDULER_STOPPED())) {
+ if (sc->sc_provider_open != 0 || SCHEDULER_STOPPED()) {
switch (how) {
case G_MIRROR_DESTROY_SOFT:
G_MIRROR_DEBUG(1,
- "Device %s is still open (r%dw%de%d).", pp->name,
- pp->acr, pp->acw, pp->ace);
+ "Device %s is still open (%d).", sc->sc_name,
+ sc->sc_provider_open);
return (EBUSY);
case G_MIRROR_DESTROY_DELAYED:
G_MIRROR_DEBUG(1,
"Device %s will be destroyed on last close.",
- pp->name);
+ sc->sc_name);
LIST_FOREACH(disk, &sc->sc_disks, d_next) {
if (disk->d_state ==
G_MIRROR_DISK_STATE_SYNCHRONIZING) {
@@ -3027,7 +3015,7 @@ g_mirror_destroy(struct g_mirror_softc *sc, int how)
return (EBUSY);
case G_MIRROR_DESTROY_HARD:
G_MIRROR_DEBUG(1, "Device %s is still open, so it "
- "can't be definitely removed.", pp->name);
+ "can't be definitely removed.", sc->sc_name);
}
}
diff --git a/sys/geom/mirror/g_mirror.h b/sys/geom/mirror/g_mirror.h
index d203b97..e730e42 100644
--- a/sys/geom/mirror/g_mirror.h
+++ b/sys/geom/mirror/g_mirror.h
@@ -179,6 +179,7 @@ struct g_mirror_softc {
struct g_geom *sc_geom;
struct g_provider *sc_provider;
+ int sc_provider_open;
uint32_t sc_id; /* Mirror unique ID. */
diff --git a/sys/geom/mirror/g_mirror_ctl.c b/sys/geom/mirror/g_mirror_ctl.c
index 2b56765..df24e52 100644
--- a/sys/geom/mirror/g_mirror_ctl.c
+++ b/sys/geom/mirror/g_mirror_ctl.c
@@ -658,8 +658,7 @@ g_mirror_ctl_resize(struct gctl_req *req, struct g_class *mp)
return;
}
/* Deny shrinking of an opened provider */
- if ((g_debugflags & 16) == 0 && (sc->sc_provider->acr > 0 ||
- sc->sc_provider->acw > 0 || sc->sc_provider->ace > 0)) {
+ if ((g_debugflags & 16) == 0 && sc->sc_provider_open > 0) {
if (sc->sc_mediasize > mediasize) {
gctl_error(req, "Device %s is busy.",
sc->sc_provider->name);
diff --git a/sys/i386/include/pcpu.h b/sys/i386/include/pcpu.h
index cfd8d03..9e35dbe 100644
--- a/sys/i386/include/pcpu.h
+++ b/sys/i386/include/pcpu.h
@@ -59,7 +59,8 @@
u_int pc_cmci_mask; /* MCx banks for CMCI */ \
u_int pc_vcpu_id; /* Xen vCPU ID */ \
vm_offset_t pc_qmap_addr; /* KVA for temporary mappings */\
- char __pad[229]
+ uint32_t pc_smp_tlb_done; /* TLB op acknowledgement */ \
+ char __pad[225]
#ifdef _KERNEL
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 341c6f4..b1d6c32 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1873,6 +1873,7 @@ __elfN(note_prpsinfo)(void *arg, struct sbuf *sb, size_t *sizep)
*cp = ' ';
}
}
+ psinfo->pr_pid = p->p_pid;
sbuf_bcat(sb, psinfo, sizeof(*psinfo));
free(psinfo, M_TEMP);
}
diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh
index b5215bd..8bab379 100644
--- a/sys/kern/makesyscalls.sh
+++ b/sys/kern/makesyscalls.sh
@@ -65,7 +65,6 @@ if [ -n "$2" ]; then
fi
sed -e '
-s/\$//g
:join
/\\$/{a\
@@ -147,7 +146,7 @@ s/\$//g
printf " * $%s$\n", "FreeBSD" > systrace
}
NR == 1 {
- gsub("[$]FreeBSD: ", "", $0)
+ gsub("[$]FreeBSD: ", "FreeBSD: ", $0)
gsub(" [$]", "", $0)
printf " * created from%s\n */\n\n", $0 > syssw
diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c
index b2297f3..c856a6e 100644
--- a/sys/kern/subr_uio.c
+++ b/sys/kern/subr_uio.c
@@ -532,7 +532,7 @@ fueword32(volatile const void *base, int32_t *val)
int
fueword64(volatile const void *base, int64_t *val)
{
- int32_t res;
+ int64_t res;
res = fuword64(base);
if (res == -1)
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 9ce8451..0a7b779 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -2637,7 +2637,7 @@ vfs_vmio_invalidate(struct buf *bp)
while (vm_page_xbusied(m)) {
vm_page_lock(m);
VM_OBJECT_WUNLOCK(obj);
- vm_page_busy_sleep(m, "mbncsh");
+ vm_page_busy_sleep(m, "mbncsh", true);
VM_OBJECT_WLOCK(obj);
}
if (pmap_page_wired_mappings(m) == 0)
@@ -4202,7 +4202,7 @@ vfs_drain_busy_pages(struct buf *bp)
while (vm_page_xbusied(m)) {
vm_page_lock(m);
VM_OBJECT_WUNLOCK(bp->b_bufobj->bo_object);
- vm_page_busy_sleep(m, "vbpage");
+ vm_page_busy_sleep(m, "vbpage", true);
VM_OBJECT_WLOCK(bp->b_bufobj->bo_object);
}
}
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 18af4ba..763caee 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -111,6 +111,7 @@ SUBDIR= \
${_epic} \
esp \
${_et} \
+ evdev \
${_ex} \
${_exca} \
ext2fs \
@@ -373,6 +374,7 @@ SUBDIR= \
udf \
udf_iconv \
ufs \
+ uinput \
unionfs \
urtwn \
${_urtwnfw} \
diff --git a/sys/modules/evdev/Makefile b/sys/modules/evdev/Makefile
new file mode 100644
index 0000000..11091ea
--- /dev/null
+++ b/sys/modules/evdev/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/evdev
+
+KMOD= evdev
+SRCS= cdev.c evdev.c evdev_mt.c evdev_utils.c
+SRCS+= opt_evdev.h bus_if.h device_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/rpi_ft5406/Makefile b/sys/modules/rpi_ft5406/Makefile
new file mode 100644
index 0000000..2360ced
--- /dev/null
+++ b/sys/modules/rpi_ft5406/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../arm/broadcom/bcm2835/
+
+KMOD= rpi_ft5406
+SRCS= bcm2835_ft5406.c
+
+SRCS+= bus_if.h device_if.h ofw_bus_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/uinput/Makefile b/sys/modules/uinput/Makefile
new file mode 100644
index 0000000..bdb9739
--- /dev/null
+++ b/sys/modules/uinput/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/evdev
+
+KMOD= uinput
+SRCS= uinput.c
+SRCS+= opt_evdev.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/usb/ukbd/Makefile b/sys/modules/usb/ukbd/Makefile
index e986191..3db978a 100644
--- a/sys/modules/usb/ukbd/Makefile
+++ b/sys/modules/usb/ukbd/Makefile
@@ -30,7 +30,7 @@ S= ${.CURDIR}/../../..
.PATH: $S/dev/usb/input
KMOD= ukbd
-SRCS= opt_bus.h opt_compat.h opt_kbd.h opt_ukbd.h opt_usb.h \
+SRCS= opt_bus.h opt_compat.h opt_evdev.h opt_kbd.h opt_ukbd.h opt_usb.h \
device_if.h bus_if.h usb_if.h usbdevs.h \
ukbd.c
diff --git a/sys/modules/usb/ums/Makefile b/sys/modules/usb/ums/Makefile
index fb24f0d..197415f 100644
--- a/sys/modules/usb/ums/Makefile
+++ b/sys/modules/usb/ums/Makefile
@@ -30,7 +30,7 @@ S= ${.CURDIR}/../../..
.PATH: $S/dev/usb/input
KMOD= ums
-SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h vnode_if.h usbdevs.h \
- ums.c
+SRCS= opt_bus.h opt_evdev.h opt_usb.h device_if.h bus_if.h usb_if.h \
+ vnode_if.h usbdevs.h ums.c
.include <bsd.kmod.mk>
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index d1caa71..34d878c 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -914,6 +914,16 @@ findpcb:
goto dropwithreset;
}
INP_WLOCK_ASSERT(inp);
+ /*
+ * While waiting for inp lock during the lookup, another thread
+ * can have dropped the inpcb, in which case we need to loop back
+ * and try to find a new inpcb to deliver to.
+ */
+ if (inp->inp_flags & INP_DROPPED) {
+ INP_WUNLOCK(inp);
+ inp = NULL;
+ goto findpcb;
+ }
if ((inp->inp_flowtype == M_HASHTYPE_NONE) &&
(M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) &&
((inp->inp_socket == NULL) ||
@@ -974,6 +984,10 @@ relocked:
if (in_pcbrele_wlocked(inp)) {
inp = NULL;
goto findpcb;
+ } else if (inp->inp_flags & INP_DROPPED) {
+ INP_WUNLOCK(inp);
+ inp = NULL;
+ goto findpcb;
}
} else
ti_locked = TI_RLOCKED;
@@ -1033,6 +1047,10 @@ relocked:
if (in_pcbrele_wlocked(inp)) {
inp = NULL;
goto findpcb;
+ } else if (inp->inp_flags & INP_DROPPED) {
+ INP_WUNLOCK(inp);
+ inp = NULL;
+ goto findpcb;
}
goto relocked;
} else
@@ -3736,7 +3754,15 @@ tcp_mss(struct tcpcb *tp, int offer)
(void)sbreserve_locked(&so->so_snd, bufsize, so, NULL);
}
SOCKBUF_UNLOCK(&so->so_snd);
- tp->t_maxseg = mss;
+ /*
+ * Sanity check: make sure that maxseg will be large
+ * enough to allow some data on segments even if the
+ * all the option space is used (40bytes). Otherwise
+ * funny things may happen in tcp_output.
+ *
+ * XXXGL: shouldn't we reserve space for IP/IPv6 options?
+ */
+ tp->t_maxseg = max(mss, 64);
SOCKBUF_LOCK(&so->so_rcv);
if ((so->so_rcv.sb_hiwat == V_tcp_recvspace) && metrics.rmx_recvpipe)
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index a8b78f9..27b965e 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -231,6 +231,10 @@ tcp_twstart(struct tcpcb *tp)
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
+ /* A dropped inp should never transition to TIME_WAIT state. */
+ KASSERT((inp->inp_flags & INP_DROPPED) == 0, ("tcp_twstart: "
+ "(inp->inp_flags & INP_DROPPED) != 0"));
+
if (V_nolocaltimewait) {
int error = 0;
#ifdef INET6
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 204c354..e86481a 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/jail.h>
+#include <sys/syslog.h>
#ifdef DDB
#include <ddb/ddb.h>
@@ -210,10 +211,26 @@ tcp_detach(struct socket *so, struct inpcb *inp)
* In all three cases the tcptw should not be freed here.
*/
if (inp->inp_flags & INP_DROPPED) {
- KASSERT(tp == NULL, ("tcp_detach: INP_TIMEWAIT && "
- "INP_DROPPED && tp != NULL"));
in_pcbdetach(inp);
- in_pcbfree(inp);
+ if (__predict_true(tp == NULL)) {
+ in_pcbfree(inp);
+ } else {
+ /*
+ * This case should not happen as in TIMEWAIT
+ * state the inp should not be destroyed before
+ * its tcptw. If INVARIANTS is defined, panic.
+ */
+#ifdef INVARIANTS
+ panic("%s: Panic before an inp double-free: "
+ "INP_TIMEWAIT && INP_DROPPED && tp != NULL"
+ , __func__);
+#else
+ log(LOG_ERR, "%s: Avoid an inp double-free: "
+ "INP_TIMEWAIT && INP_DROPPED && tp != NULL"
+ , __func__);
+#endif
+ INP_WUNLOCK(inp);
+ }
} else {
in_pcbdetach(inp);
INP_WUNLOCK(inp);
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 173c44c..76fc7fa 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1559,12 +1559,18 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
release:
if (unlock_udbinfo == UH_WLOCKED) {
+ KASSERT(unlock_inp == UH_WLOCKED,
+ ("%s: excl udbinfo lock, shared inp lock", __func__));
INP_HASH_WUNLOCK(pcbinfo);
INP_WUNLOCK(inp);
} else if (unlock_udbinfo == UH_RLOCKED) {
+ KASSERT(unlock_inp == UH_RLOCKED,
+ ("%s: shared udbinfo lock, excl inp lock", __func__));
INP_HASH_RUNLOCK(pcbinfo);
INP_RUNLOCK(inp);
- } else
+ } else if (unlock_inp == UH_WLOCKED)
+ INP_WUNLOCK(inp);
+ else
INP_RUNLOCK(inp);
m_freem(m);
return (error);
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index ef9e374..0a162eb 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1227,7 +1227,7 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
struct ifaddr *dstaddr;
struct rt_addrinfo info;
struct sockaddr_in6 rt_key;
- struct sockaddr *dst6;
+ const struct sockaddr *dst6;
int fibnum;
/*
@@ -1273,7 +1273,7 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) {
/* Always use the default FIB here. */
- dst6 = (struct sockaddr *)&pr->ndpr_prefix;
+ dst6 = (const struct sockaddr *)&pr->ndpr_prefix;
/* Restore length field before retrying lookup */
rt_key.sin6_len = sizeof(rt_key);
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index c9c7056..031727b 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -76,17 +76,16 @@ static int prelist_update(struct nd_prefixctl *, struct nd_defrouter *,
struct mbuf *, int);
static struct in6_ifaddr *in6_ifadd(struct nd_prefixctl *, int);
static struct nd_pfxrouter *pfxrtr_lookup(struct nd_prefix *,
- struct nd_defrouter *);
+ struct nd_defrouter *);
static void pfxrtr_add(struct nd_prefix *, struct nd_defrouter *);
static void pfxrtr_del(struct nd_pfxrouter *);
-static struct nd_pfxrouter *find_pfxlist_reachable_router
-(struct nd_prefix *);
+static struct nd_pfxrouter *find_pfxlist_reachable_router(struct nd_prefix *);
static void defrouter_delreq(struct nd_defrouter *);
static void nd6_rtmsg(int, struct rtentry *);
static int in6_init_prefix_ltimes(struct nd_prefix *);
static void in6_init_address_ltimes(struct nd_prefix *,
- struct in6_addrlifetime *);
+ struct in6_addrlifetime *);
static int nd6_prefix_onlink(struct nd_prefix *);
static int nd6_prefix_offlink(struct nd_prefix *);
@@ -1432,7 +1431,7 @@ find_pfxlist_reachable_router(struct nd_prefix *pr)
* we have moved from the network but the lifetime of the prefix has not
* expired yet. So we should not use the prefix if there is another prefix
* that has an available router.
- * But, if there is no prefix that has an available router, we still regards
+ * But, if there is no prefix that has an available router, we still regard
* all the prefixes as on-link. This is because we can't tell if all the
* routers are simply dead or if we really moved from the network and there
* is no router around us.
@@ -1485,40 +1484,26 @@ pfxlist_onlink_check(void)
*/
LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
/* XXX: a link-local prefix should never be detached */
- if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
- continue;
-
- /*
- * we aren't interested in prefixes without the L bit
- * set.
- */
- if (pr->ndpr_raf_onlink == 0)
- continue;
-
- if (pr->ndpr_raf_auto == 0)
+ if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) ||
+ pr->ndpr_raf_onlink == 0 ||
+ pr->ndpr_raf_auto == 0)
continue;
if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
find_pfxlist_reachable_router(pr) == NULL)
pr->ndpr_stateflags |= NDPRF_DETACHED;
- if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
+ else if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
find_pfxlist_reachable_router(pr) != NULL)
pr->ndpr_stateflags &= ~NDPRF_DETACHED;
}
} else {
/* there is no prefix that has a reachable router */
LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
- if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
+ if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) ||
+ pr->ndpr_raf_onlink == 0 ||
+ pr->ndpr_raf_auto == 0)
continue;
-
- if (pr->ndpr_raf_onlink == 0)
- continue;
-
- if (pr->ndpr_raf_auto == 0)
- continue;
-
- if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0)
- pr->ndpr_stateflags &= ~NDPRF_DETACHED;
+ pr->ndpr_stateflags &= ~NDPRF_DETACHED;
}
}
@@ -1531,16 +1516,12 @@ pfxlist_onlink_check(void)
* so we don't have to care about them.
*/
LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
- int e;
char ip6buf[INET6_ADDRSTRLEN];
+ int e;
- if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
- continue;
-
- if (pr->ndpr_raf_onlink == 0)
- continue;
-
- if (pr->ndpr_raf_auto == 0)
+ if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) ||
+ pr->ndpr_raf_onlink == 0 ||
+ pr->ndpr_raf_auto == 0)
continue;
if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
@@ -1753,11 +1734,11 @@ nd6_prefix_onlink(struct nd_prefix *pr)
/* XXX: freebsd does not have ifa_ifwithaf */
IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- if (ifa->ifa_addr->sa_family == AF_INET6)
+ if (ifa->ifa_addr->sa_family == AF_INET6) {
+ ifa_ref(ifa);
break;
+ }
}
- if (ifa != NULL)
- ifa_ref(ifa);
IF_ADDR_RUNLOCK(ifp);
/* should we care about ia6_flags? */
}
@@ -1844,17 +1825,12 @@ nd6_prefix_offlink(struct nd_prefix *pr)
* interface.
*/
LIST_FOREACH(opr, &V_nd_prefix, ndpr_entry) {
- if (opr == pr)
- continue;
-
- if ((opr->ndpr_stateflags & NDPRF_ONLINK) != 0)
- continue;
-
/*
* KAME specific: detached prefixes should not be
* on-link.
*/
- if ((opr->ndpr_stateflags & NDPRF_DETACHED) != 0)
+ if (opr == pr || (opr->ndpr_stateflags &
+ (NDPRF_ONLINK | NDPRF_DETACHED)) != 0)
continue;
if (opr->ndpr_plen == pr->ndpr_plen &&
diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c
index 47114ea..0f3673a 100644
--- a/sys/netpfil/ipfw/ip_fw_table.c
+++ b/sys/netpfil/ipfw/ip_fw_table.c
@@ -1087,6 +1087,7 @@ find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
struct table_config *tc;
struct table_algo *ta;
struct table_info *kti;
+ struct table_value *pval;
struct namedobj_instance *ni;
int error;
size_t sz;
@@ -1132,7 +1133,10 @@ find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
return (ENOTSUP);
error = ta->find_tentry(tc->astate, kti, tent);
-
+ if (error == 0) {
+ pval = get_table_value(ch, tc, tent->v.kidx);
+ ipfw_export_table_value_v1(pval, &tent->v.value);
+ }
IPFW_UH_RUNLOCK(ch);
return (error);
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 10149f6..9308ac3 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -44,7 +44,7 @@
#define BSD4_3 1
#define BSD4_4 1
-/*
+/*
* __FreeBSD_version numbers are documented in the Porter's Handbook.
* If you bump the version for any reason, you should update the documentation
* there.
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1100505 /* Master, propagated to newvers */
+#define __FreeBSD_version 1100506 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
@@ -241,7 +241,7 @@
*
* BKVASIZE - Nominal buffer space per buffer, in bytes. BKVASIZE is the
* minimum KVM memory reservation the kernel is willing to make.
- * Filesystems can of course request smaller chunks. Actual
+ * Filesystems can of course request smaller chunks. Actual
* backing memory uses a chunk size of a page (PAGE_SIZE).
* The default value here can be overridden on a per-architecture
* basis by defining it in <machine/param.h>. This should
@@ -250,8 +250,8 @@
*
* If you make BKVASIZE too small you risk seriously fragmenting
* the buffer KVM map which may slow things down a bit. If you
- * make it too big the kernel will not be able to optimally use
- * the KVM memory reserved for the buffer cache and will wind
+ * make it too big the kernel will not be able to optimally use
+ * the KVM memory reserved for the buffer cache and will wind
* up with too-few buffers.
*
* The default is 16384, roughly 2x the block size used by a
@@ -344,7 +344,7 @@ __END_DECLS
#define dbtoc(db) /* calculates devblks to pages */ \
((db + (ctodb(1) - 1)) >> (PAGE_SHIFT - DEV_BSHIFT))
-
+
#define ctodb(db) /* calculates pages to devblks */ \
((db) << (PAGE_SHIFT - DEV_BSHIFT))
diff --git a/sys/sys/procfs.h b/sys/sys/procfs.h
index 6b32dfd..5f857ef 100644
--- a/sys/sys/procfs.h
+++ b/sys/sys/procfs.h
@@ -49,7 +49,10 @@ typedef struct fpreg fpregset_t;
/*
* The parenthsized numbers like (1) indicate the minimum version number
- * for which each element exists in the structure.
+ * for which each element exists in the structure. The version number is
+ * not bumped when adding new fields to the end, only if the meaning of
+ * an existing field changes. Additional fields are annotated as (1a),
+ * (1b), etc. to indicate the groupings of additions.
*/
#define PRSTATUS_VERSION 1 /* Current version of prstatus_t */
@@ -61,7 +64,7 @@ typedef struct prstatus {
size_t pr_fpregsetsz; /* sizeof(fpregset_t) (1) */
int pr_osreldate; /* Kernel version (1) */
int pr_cursig; /* Current signal (1) */
- pid_t pr_pid; /* Process ID (1) */
+ pid_t pr_pid; /* LWP (Thread) ID (1) */
gregset_t pr_reg; /* General purpose registers (1) */
} prstatus_t;
@@ -78,6 +81,7 @@ typedef struct prpsinfo {
size_t pr_psinfosz; /* sizeof(prpsinfo_t) (1) */
char pr_fname[PRFNAMESZ+1]; /* Command name, null terminated (1) */
char pr_psargs[PRARGSZ+1]; /* Arguments, null terminated (1) */
+ pid_t pr_pid; /* Process ID (1a) */
} prpsinfo_t;
typedef struct thrmisc {
@@ -104,6 +108,7 @@ typedef struct prpsinfo32 {
uint32_t pr_psinfosz;
char pr_fname[PRFNAMESZ+1];
char pr_psargs[PRARGSZ+1];
+ int32_t pr_pid;
} prpsinfo32_t;
struct thrmisc32 {
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index cdcff7e..fb40167 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -77,6 +77,7 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/rwlock.h>
#include <sys/stat.h>
+#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <sys/vnode.h>
@@ -86,6 +87,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <vm/vm_pager.h>
+#include <vm/vm_pageout.h>
#include <vm/vnode_pager.h>
#include <ufs/ufs/extattr.h>
@@ -102,8 +104,9 @@ __FBSDID("$FreeBSD$");
#ifdef DIRECTIO
extern int ffs_rawread(struct vnode *vp, struct uio *uio, int *workdone);
#endif
-static vop_fsync_t ffs_fsync;
static vop_fdatasync_t ffs_fdatasync;
+static vop_fsync_t ffs_fsync;
+static vop_getpages_t ffs_getpages;
static vop_lock1_t ffs_lock;
static vop_read_t ffs_read;
static vop_write_t ffs_write;
@@ -119,13 +122,12 @@ static vop_openextattr_t ffs_openextattr;
static vop_setextattr_t ffs_setextattr;
static vop_vptofh_t ffs_vptofh;
-
/* Global vfs data structures for ufs. */
struct vop_vector ffs_vnodeops1 = {
.vop_default = &ufs_vnodeops,
.vop_fsync = ffs_fsync,
.vop_fdatasync = ffs_fdatasync,
- .vop_getpages = vnode_pager_local_getpages,
+ .vop_getpages = ffs_getpages,
.vop_getpages_async = vnode_pager_local_getpages_async,
.vop_lock1 = ffs_lock,
.vop_read = ffs_read,
@@ -147,7 +149,7 @@ struct vop_vector ffs_vnodeops2 = {
.vop_default = &ufs_vnodeops,
.vop_fsync = ffs_fsync,
.vop_fdatasync = ffs_fdatasync,
- .vop_getpages = vnode_pager_local_getpages,
+ .vop_getpages = ffs_getpages,
.vop_getpages_async = vnode_pager_local_getpages_async,
.vop_lock1 = ffs_lock,
.vop_read = ffs_read,
@@ -1784,3 +1786,165 @@ vop_vptofh {
ufhp->ufid_gen = ip->i_gen;
return (0);
}
+
+SYSCTL_DECL(_vfs_ffs);
+static int use_buf_pager = 0;
+SYSCTL_INT(_vfs_ffs, OID_AUTO, use_buf_pager, CTLFLAG_RWTUN, &use_buf_pager, 0,
+ "Always use buffer pager instead of bmap");
+static int buf_pager_relbuf;
+SYSCTL_INT(_vfs_ffs, OID_AUTO, buf_pager_relbuf, CTLFLAG_RWTUN,
+ &buf_pager_relbuf, 0,
+ "Make buffer pager release buffers after reading");
+
+/*
+ * The FFS pager. It uses buffer reads to validate pages.
+ *
+ * In contrast to the generic local pager from vm/vnode_pager.c, this
+ * pager correctly and easily handles volumes where the underlying
+ * device block size is greater than the machine page size. The
+ * buffer cache transparently extends the requested page run to be
+ * aligned at the block boundary, and does the necessary bogus page
+ * replacements in the addends to avoid obliterating already valid
+ * pages.
+ *
+ * The only non-trivial issue is that the exclusive busy state for
+ * pages, which is assumed by the vm_pager_getpages() interface, is
+ * incompatible with the VMIO buffer cache's desire to share-busy the
+ * pages. This function performs a trivial downgrade of the pages'
+ * state before reading buffers, and a less trivial upgrade from the
+ * shared-busy to excl-busy state after the read.
+ */
+static int
+ffs_getpages(struct vop_getpages_args *ap)
+{
+ struct vnode *vp;
+ vm_page_t *ma, m;
+ vm_object_t object;
+ struct buf *bp;
+ struct ufsmount *um;
+ ufs_lbn_t lbn, lbnp;
+ vm_ooffset_t la, lb;
+ long bsize;
+ int bo_bs, count, error, i;
+ bool redo, lpart;
+
+ vp = ap->a_vp;
+ ma = ap->a_m;
+ count = ap->a_count;
+
+ um = VFSTOUFS(ap->a_vp->v_mount);
+ bo_bs = um->um_devvp->v_bufobj.bo_bsize;
+ if (!use_buf_pager && bo_bs <= PAGE_SIZE)
+ return (vnode_pager_generic_getpages(vp, ma, count,
+ ap->a_rbehind, ap->a_rahead, NULL, NULL));
+
+ object = vp->v_object;
+ la = IDX_TO_OFF(ma[count - 1]->pindex);
+ if (la >= object->un_pager.vnp.vnp_size)
+ return (VM_PAGER_BAD);
+ lpart = la + PAGE_SIZE > object->un_pager.vnp.vnp_size;
+ if (ap->a_rbehind != NULL) {
+ lb = IDX_TO_OFF(ma[0]->pindex);
+ *ap->a_rbehind = OFF_TO_IDX(lb - rounddown2(lb, bo_bs));
+ }
+ if (ap->a_rahead != NULL) {
+ *ap->a_rahead = OFF_TO_IDX(roundup2(la, bo_bs) - la);
+ if (la + IDX_TO_OFF(*ap->a_rahead) >=
+ object->un_pager.vnp.vnp_size) {
+ *ap->a_rahead = OFF_TO_IDX(roundup2(object->un_pager.
+ vnp.vnp_size, PAGE_SIZE) - la);
+ }
+ }
+ VM_OBJECT_WLOCK(object);
+again:
+ for (i = 0; i < count; i++)
+ vm_page_busy_downgrade(ma[i]);
+ VM_OBJECT_WUNLOCK(object);
+
+ lbnp = -1;
+ for (i = 0; i < count; i++) {
+ m = ma[i];
+
+ /*
+ * Pages are shared busy and the object lock is not
+ * owned, which together allow for the pages'
+ * invalidation. The racy test for validity avoids
+ * useless creation of the buffer for the most typical
+ * case when invalidation is not used in redo or for
+ * parallel read. The shared->excl upgrade loop at
+ * the end of the function catches the race in a
+ * reliable way (protected by the object lock).
+ */
+ if (m->valid == VM_PAGE_BITS_ALL)
+ continue;
+
+ lbn = lblkno(um->um_fs, IDX_TO_OFF(m->pindex));
+ if (lbn != lbnp) {
+ bsize = blksize(um->um_fs, VTOI(vp), lbn);
+ error = bread_gb(vp, lbn, bsize, NOCRED, GB_UNMAPPED,
+ &bp);
+ if (error != 0)
+ break;
+ KASSERT(1 /* racy, enable for debugging */ ||
+ m->valid == VM_PAGE_BITS_ALL || i == count - 1,
+ ("buf %d %p invalid", i, m));
+ if (i == count - 1 && lpart) {
+ VM_OBJECT_WLOCK(object);
+ if (m->valid != 0 &&
+ m->valid != VM_PAGE_BITS_ALL)
+ vm_page_zero_invalid(m, TRUE);
+ VM_OBJECT_WUNLOCK(object);
+ }
+ if (LIST_EMPTY(&bp->b_dep)) {
+ /*
+ * Invalidation clears m->valid, but
+ * may leave B_CACHE flag if the
+ * buffer existed at the invalidation
+ * time. In this case, recycle the
+ * buffer to do real read on next
+ * bread() after redo.
+ *
+ * Otherwise B_RELBUF is not strictly
+ * necessary, enable to reduce buf
+ * cache pressure.
+ */
+ if (buf_pager_relbuf ||
+ m->valid != VM_PAGE_BITS_ALL)
+ bp->b_flags |= B_RELBUF;
+
+ bp->b_flags &= ~B_NOCACHE;
+ brelse(bp);
+ } else {
+ bqrelse(bp);
+ }
+ lbnp = lbn;
+ }
+ }
+
+ VM_OBJECT_WLOCK(object);
+ redo = false;
+ for (i = 0; i < count; i++) {
+ vm_page_sunbusy(ma[i]);
+ ma[i] = vm_page_grab(object, ma[i]->pindex, VM_ALLOC_NORMAL);
+
+ /*
+ * Since the pages were only sbusy while neither the
+ * buffer nor the object lock was held by us, or
+ * reallocated while vm_page_grab() slept for busy
+ * relinguish, they could have been invalidated.
+ * Recheck the valid bits and re-read as needed.
+ *
+ * Note that the last page is made fully valid in the
+ * read loop, and partial validity for the page at
+ * index count - 1 could mean that the page was
+ * invalidated or removed, so we must restart for
+ * safety as well.
+ */
+ if (ma[i]->valid != VM_PAGE_BITS_ALL)
+ redo = true;
+ }
+ if (redo && error == 0)
+ goto again;
+ VM_OBJECT_WUNLOCK(object);
+ return (error != 0 ? VM_PAGER_ERROR : VM_PAGER_OK);
+}
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 050ddddaa..03c68dd 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -321,6 +321,8 @@ RetryFault:;
growstack = FALSE;
goto RetryFault;
}
+ if (fs.vp != NULL)
+ vput(fs.vp);
return (result);
}
@@ -720,7 +722,10 @@ vnode_locked:
*/
if (rv == VM_PAGER_ERROR || rv == VM_PAGER_BAD) {
vm_page_lock(fs.m);
- vm_page_free(fs.m);
+ if (fs.m->wire_count == 0)
+ vm_page_free(fs.m);
+ else
+ vm_page_xunbusy_maybelocked(fs.m);
vm_page_unlock(fs.m);
fs.m = NULL;
unlock_and_deallocate(&fs);
@@ -740,7 +745,10 @@ vnode_locked:
*/
if (fs.object != fs.first_object) {
vm_page_lock(fs.m);
- vm_page_free(fs.m);
+ if (fs.m->wire_count == 0)
+ vm_page_free(fs.m);
+ else
+ vm_page_xunbusy_maybelocked(fs.m);
vm_page_unlock(fs.m);
fs.m = NULL;
}
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 17723c7..7321990 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -1186,7 +1186,7 @@ shadowlookup:
if (object != tobject)
VM_OBJECT_WUNLOCK(object);
VM_OBJECT_WUNLOCK(tobject);
- vm_page_busy_sleep(m, "madvpo");
+ vm_page_busy_sleep(m, "madvpo", false);
VM_OBJECT_WLOCK(object);
goto relookup;
}
@@ -1365,7 +1365,7 @@ retry:
VM_OBJECT_WUNLOCK(new_object);
vm_page_lock(m);
VM_OBJECT_WUNLOCK(orig_object);
- vm_page_busy_sleep(m, "spltwt");
+ vm_page_busy_sleep(m, "spltwt", false);
VM_OBJECT_WLOCK(orig_object);
VM_OBJECT_WLOCK(new_object);
goto retry;
@@ -1453,7 +1453,7 @@ vm_object_collapse_scan_wait(vm_object_t object, vm_page_t p, vm_page_t next,
if (p == NULL)
VM_WAIT;
else
- vm_page_busy_sleep(p, "vmocol");
+ vm_page_busy_sleep(p, "vmocol", false);
VM_OBJECT_WLOCK(object);
VM_OBJECT_WLOCK(backing_object);
return (TAILQ_FIRST(&backing_object->memq));
@@ -1912,7 +1912,7 @@ again:
vm_page_lock(p);
if (vm_page_xbusied(p)) {
VM_OBJECT_WUNLOCK(object);
- vm_page_busy_sleep(p, "vmopax");
+ vm_page_busy_sleep(p, "vmopax", true);
VM_OBJECT_WLOCK(object);
goto again;
}
@@ -1927,7 +1927,7 @@ again:
}
if (vm_page_busied(p)) {
VM_OBJECT_WUNLOCK(object);
- vm_page_busy_sleep(p, "vmopar");
+ vm_page_busy_sleep(p, "vmopar", false);
VM_OBJECT_WLOCK(object);
goto again;
}
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 2d3b160..8bf8549 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -395,7 +395,6 @@ vm_page_domain_init(struct vm_domain *vmd)
vmd->vmd_free_count = 0;
vmd->vmd_segs = 0;
vmd->vmd_oom = FALSE;
- vmd->vmd_pass = 0;
for (i = 0; i < PQ_COUNT; i++) {
pq = &vmd->vmd_pagequeues[i];
TAILQ_INIT(&pq->pq_pl);
@@ -743,21 +742,20 @@ vm_page_sunbusy(vm_page_t m)
* This is used to implement the hard-path of busying mechanism.
*
* The given page must be locked.
+ *
+ * If nonshared is true, sleep only if the page is xbusy.
*/
void
-vm_page_busy_sleep(vm_page_t m, const char *wmesg)
+vm_page_busy_sleep(vm_page_t m, const char *wmesg, bool nonshared)
{
u_int x;
- vm_page_lock_assert(m, MA_OWNED);
+ vm_page_assert_locked(m);
x = m->busy_lock;
- if (x == VPB_UNBUSIED) {
- vm_page_unlock(m);
- return;
- }
- if ((x & VPB_BIT_WAITERS) == 0 &&
- !atomic_cmpset_int(&m->busy_lock, x, x | VPB_BIT_WAITERS)) {
+ if (x == VPB_UNBUSIED || (nonshared && (x & VPB_BIT_SHARED) != 0) ||
+ ((x & VPB_BIT_WAITERS) == 0 &&
+ !atomic_cmpset_int(&m->busy_lock, x, x | VPB_BIT_WAITERS))) {
vm_page_unlock(m);
return;
}
@@ -797,7 +795,7 @@ vm_page_xunbusy_locked(vm_page_t m)
wakeup(m);
}
-static void
+void
vm_page_xunbusy_maybelocked(vm_page_t m)
{
bool lockacq;
@@ -1094,7 +1092,7 @@ vm_page_sleep_if_busy(vm_page_t m, const char *msg)
obj = m->object;
vm_page_lock(m);
VM_OBJECT_WUNLOCK(obj);
- vm_page_busy_sleep(m, msg);
+ vm_page_busy_sleep(m, msg, false);
VM_OBJECT_WLOCK(obj);
return (TRUE);
}
@@ -3466,7 +3464,8 @@ retrylookup:
vm_page_aflag_set(m, PGA_REFERENCED);
vm_page_lock(m);
VM_OBJECT_WUNLOCK(object);
- vm_page_busy_sleep(m, "pgrbwt");
+ vm_page_busy_sleep(m, "pgrbwt", (allocflags &
+ VM_ALLOC_IGN_SBUSY) != 0);
VM_OBJECT_WLOCK(object);
goto retrylookup;
} else {
@@ -3949,14 +3948,12 @@ DB_SHOW_COMMAND(pageq, vm_page_print_pageq_info)
db_printf("pq_free %d pq_cache %d\n",
vm_cnt.v_free_count, vm_cnt.v_cache_count);
for (dom = 0; dom < vm_ndomains; dom++) {
- db_printf(
- "dom %d page_cnt %d free %d pq_act %d pq_inact %d pass %d\n",
+ db_printf("dom %d page_cnt %d free %d pq_act %d pq_inact %d\n",
dom,
vm_dom[dom].vmd_page_count,
vm_dom[dom].vmd_free_count,
vm_dom[dom].vmd_pagequeues[PQ_ACTIVE].pq_cnt,
- vm_dom[dom].vmd_pagequeues[PQ_INACTIVE].pq_cnt,
- vm_dom[dom].vmd_pass);
+ vm_dom[dom].vmd_pagequeues[PQ_INACTIVE].pq_cnt);
}
}
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index c915598..85c6ac5 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -226,7 +226,6 @@ struct vm_domain {
u_int vmd_free_count;
long vmd_segs; /* bitmask of the segments */
boolean_t vmd_oom;
- int vmd_pass; /* local pagedaemon pass */
int vmd_oom_seq;
int vmd_last_active_scan;
struct vm_page vmd_marker; /* marker for pagedaemon private use */
@@ -437,7 +436,7 @@ malloc2vm_flags(int malloc_flags)
#endif
void vm_page_busy_downgrade(vm_page_t m);
-void vm_page_busy_sleep(vm_page_t m, const char *msg);
+void vm_page_busy_sleep(vm_page_t m, const char *msg, bool nonshared);
void vm_page_flash(vm_page_t m);
void vm_page_hold(vm_page_t mem);
void vm_page_unhold(vm_page_t mem);
@@ -496,6 +495,7 @@ boolean_t vm_page_unwire(vm_page_t m, uint8_t queue);
void vm_page_updatefake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr);
void vm_page_wire (vm_page_t);
void vm_page_xunbusy_hard(vm_page_t m);
+void vm_page_xunbusy_maybelocked(vm_page_t m);
void vm_page_set_validclean (vm_page_t, int, int);
void vm_page_clear_dirty (vm_page_t, int, int);
void vm_page_set_invalid (vm_page_t, int, int);
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 2befbc7..ed9d439 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -121,7 +121,7 @@ static void vm_pageout(void);
static void vm_pageout_init(void);
static int vm_pageout_clean(vm_page_t m);
static int vm_pageout_cluster(vm_page_t m);
-static void vm_pageout_scan(struct vm_domain *vmd, int pass);
+static bool vm_pageout_scan(struct vm_domain *vmd, int pass);
static void vm_pageout_mightbe_oom(struct vm_domain *vmd, int page_shortage,
int starting_page_shortage);
@@ -845,17 +845,20 @@ unlock_mp:
* pass 0 - Update active LRU/deactivate pages
* pass 1 - Free inactive pages
* pass 2 - Launder dirty pages
+ *
+ * Returns true if pass was zero or enough pages were freed by the inactive
+ * queue scan to meet the target.
*/
-static void
+static bool
vm_pageout_scan(struct vm_domain *vmd, int pass)
{
vm_page_t m, next;
struct vm_pagequeue *pq;
vm_object_t object;
long min_scan;
- int act_delta, addl_page_shortage, deficit, error, maxlaunder, maxscan;
- int page_shortage, scan_tick, scanned, starting_page_shortage;
- int vnodes_skipped;
+ int act_delta, addl_page_shortage, deficit, error, inactq_shortage;
+ int maxlaunder, maxscan, page_shortage, scan_tick, scanned;
+ int starting_page_shortage, vnodes_skipped;
boolean_t pageout_ok, queue_locked;
/*
@@ -886,7 +889,9 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
addl_page_shortage = 0;
/*
- * Calculate the number of pages that we want to free.
+ * Calculate the number of pages that we want to free. This number
+ * can be negative if many pages are freed between the wakeup call to
+ * the page daemon and this calculation.
*/
if (pass > 0) {
deficit = atomic_readandclear_int(&vm_pageout_deficit);
@@ -956,7 +961,7 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
* Held pages are essentially stuck in the
* queue. So, they ought to be discounted
* from the inactive count. See the
- * calculation of the page_shortage for the
+ * calculation of inactq_shortage before the
* loop over the active queue below.
*/
addl_page_shortage++;
@@ -1164,7 +1169,7 @@ relock_queue:
* Compute the number of pages we want to try to move from the
* active queue to the inactive queue.
*/
- page_shortage = vm_cnt.v_inactive_target - vm_cnt.v_inactive_count +
+ inactq_shortage = vm_cnt.v_inactive_target - vm_cnt.v_inactive_count +
vm_paging_target() + deficit + addl_page_shortage;
pq = &vmd->vmd_pagequeues[PQ_ACTIVE];
@@ -1182,7 +1187,7 @@ relock_queue:
min_scan /= hz * vm_pageout_update_period;
} else
min_scan = 0;
- if (min_scan > 0 || (page_shortage > 0 && maxscan > 0))
+ if (min_scan > 0 || (inactq_shortage > 0 && maxscan > 0))
vmd->vmd_last_active_scan = scan_tick;
/*
@@ -1191,7 +1196,7 @@ relock_queue:
* candidates. Held pages may be deactivated.
*/
for (m = TAILQ_FIRST(&pq->pq_pl), scanned = 0; m != NULL && (scanned <
- min_scan || (page_shortage > 0 && scanned < maxscan)); m = next,
+ min_scan || (inactq_shortage > 0 && scanned < maxscan)); m = next,
scanned++) {
KASSERT(m->queue == PQ_ACTIVE,
("vm_pageout_scan: page %p isn't active", m));
@@ -1256,7 +1261,7 @@ relock_queue:
/* Dequeue to avoid later lock recursion. */
vm_page_dequeue_locked(m);
vm_page_deactivate(m);
- page_shortage--;
+ inactq_shortage--;
} else
vm_page_requeue_locked(m);
vm_page_unlock(m);
@@ -1274,6 +1279,7 @@ relock_queue:
}
}
#endif
+ return (page_shortage <= 0);
}
static int vm_pageout_oom_vote;
@@ -1502,10 +1508,13 @@ static void
vm_pageout_worker(void *arg)
{
struct vm_domain *domain;
- int domidx;
+ int domidx, pass;
+ bool target_met;
domidx = (uintptr_t)arg;
domain = &vm_dom[domidx];
+ pass = 0;
+ target_met = true;
/*
* XXXKIB It could be useful to bind pageout daemon threads to
@@ -1544,11 +1553,11 @@ vm_pageout_worker(void *arg)
}
/*
- * Do not clear vm_pageout_wanted until we reach our target.
- * Otherwise, we may be awakened over and over again, wasting
- * CPU time.
+ * Do not clear vm_pageout_wanted until we reach our free page
+ * target. Otherwise, we may be awakened over and over again,
+ * wasting CPU time.
*/
- if (vm_pageout_wanted && !vm_paging_needed())
+ if (vm_pageout_wanted && target_met)
vm_pageout_wanted = false;
/*
@@ -1566,9 +1575,9 @@ vm_pageout_worker(void *arg)
* and try again later.
*/
mtx_unlock(&vm_page_queue_free_mtx);
- if (domain->vmd_pass > 1)
+ if (pass > 1)
pause("psleep", hz / 2);
- domain->vmd_pass++;
+ pass++;
} else {
/*
* Yes. Sleep until pages need to be reclaimed or
@@ -1578,12 +1587,12 @@ vm_pageout_worker(void *arg)
&vm_page_queue_free_mtx, PDROP | PVM, "psleep",
hz) == 0) {
PCPU_INC(cnt.v_pdwakeups);
- domain->vmd_pass = 1;
+ pass = 1;
} else
- domain->vmd_pass = 0;
+ pass = 0;
}
- vm_pageout_scan(domain, domain->vmd_pass);
+ target_met = vm_pageout_scan(domain, pass);
}
}
diff --git a/sys/x86/include/x86_smp.h b/sys/x86/include/x86_smp.h
index 38d7625..7c906dd 100644
--- a/sys/x86/include/x86_smp.h
+++ b/sys/x86/include/x86_smp.h
@@ -35,7 +35,7 @@ extern volatile int aps_ready;
extern struct mtx ap_boot_mtx;
extern int cpu_logical;
extern int cpu_cores;
-extern volatile int smp_tlb_wait;
+extern volatile uint32_t smp_tlb_generation;
extern struct pmap *smp_tlb_pmap;
extern u_int xhits_gbl[];
extern u_int xhits_pg[];
diff --git a/sys/x86/x86/mp_x86.c b/sys/x86/x86/mp_x86.c
index d2eb2e9..6ef72f9 100644
--- a/sys/x86/x86/mp_x86.c
+++ b/sys/x86/x86/mp_x86.c
@@ -1308,12 +1308,22 @@ cpususpend_handler(void)
void
invlcache_handler(void)
{
+ uint32_t generation;
+
#ifdef COUNT_IPIS
(*ipi_invlcache_counts[PCPU_GET(cpuid)])++;
#endif /* COUNT_IPIS */
+ /*
+ * Reading the generation here allows greater parallelism
+ * since wbinvd is a serializing instruction. Without the
+ * temporary, we'd wait for wbinvd to complete, then the read
+ * would execute, then the dependent write, which must then
+ * complete before return from interrupt.
+ */
+ generation = smp_tlb_generation;
wbinvd();
- atomic_add_int(&smp_tlb_wait, 1);
+ PCPU_SET(smp_tlb_done, generation);
}
/*
@@ -1371,7 +1381,7 @@ SYSINIT(mp_ipi_intrcnt, SI_SUB_INTR, SI_ORDER_MIDDLE, mp_ipi_intrcnt, NULL);
/* Variables needed for SMP tlb shootdown. */
static vm_offset_t smp_tlb_addr1, smp_tlb_addr2;
pmap_t smp_tlb_pmap;
-volatile int smp_tlb_wait;
+volatile uint32_t smp_tlb_generation;
#ifdef __amd64__
#define read_eflags() read_rflags()
@@ -1381,15 +1391,16 @@ static void
smp_targeted_tlb_shootdown(cpuset_t mask, u_int vector, pmap_t pmap,
vm_offset_t addr1, vm_offset_t addr2)
{
- int cpu, ncpu, othercpus;
-
- othercpus = mp_ncpus - 1; /* does not shootdown self */
+ cpuset_t other_cpus;
+ volatile uint32_t *p_cpudone;
+ uint32_t generation;
+ int cpu;
/*
* Check for other cpus. Return if none.
*/
if (CPU_ISFULLSET(&mask)) {
- if (othercpus < 1)
+ if (mp_ncpus <= 1)
return;
} else {
CPU_CLR(PCPU_GET(cpuid), &mask);
@@ -1403,23 +1414,28 @@ smp_targeted_tlb_shootdown(cpuset_t mask, u_int vector, pmap_t pmap,
smp_tlb_addr1 = addr1;
smp_tlb_addr2 = addr2;
smp_tlb_pmap = pmap;
- smp_tlb_wait = 0;
+ generation = ++smp_tlb_generation;
if (CPU_ISFULLSET(&mask)) {
- ncpu = othercpus;
ipi_all_but_self(vector);
+ other_cpus = all_cpus;
+ CPU_CLR(PCPU_GET(cpuid), &other_cpus);
} else {
- ncpu = 0;
+ other_cpus = mask;
while ((cpu = CPU_FFS(&mask)) != 0) {
cpu--;
CPU_CLR(cpu, &mask);
CTR3(KTR_SMP, "%s: cpu: %d ipi: %x", __func__,
cpu, vector);
ipi_send_cpu(cpu, vector);
- ncpu++;
}
}
- while (smp_tlb_wait < ncpu)
- ia32_pause();
+ while ((cpu = CPU_FFS(&other_cpus)) != 0) {
+ cpu--;
+ CPU_CLR(cpu, &other_cpus);
+ p_cpudone = &cpuid_to_pcpu[cpu]->pc_smp_tlb_done;
+ while (*p_cpudone != generation)
+ ia32_pause();
+ }
mtx_unlock_spin(&smp_ipi_mtx);
}
@@ -1477,6 +1493,8 @@ smp_cache_flush(void)
void
invltlb_handler(void)
{
+ uint32_t generation;
+
#ifdef COUNT_XINVLTLB_HITS
xhits_gbl[PCPU_GET(cpuid)]++;
#endif /* COUNT_XINVLTLB_HITS */
@@ -1484,16 +1502,23 @@ invltlb_handler(void)
(*ipi_invltlb_counts[PCPU_GET(cpuid)])++;
#endif /* COUNT_IPIS */
+ /*
+ * Reading the generation here allows greater parallelism
+ * since invalidating the TLB is a serializing operation.
+ */
+ generation = smp_tlb_generation;
if (smp_tlb_pmap == kernel_pmap)
invltlb_glob();
else
invltlb();
- atomic_add_int(&smp_tlb_wait, 1);
+ PCPU_SET(smp_tlb_done, generation);
}
void
invlpg_handler(void)
{
+ uint32_t generation;
+
#ifdef COUNT_XINVLTLB_HITS
xhits_pg[PCPU_GET(cpuid)]++;
#endif /* COUNT_XINVLTLB_HITS */
@@ -1501,14 +1526,16 @@ invlpg_handler(void)
(*ipi_invlpg_counts[PCPU_GET(cpuid)])++;
#endif /* COUNT_IPIS */
+ generation = smp_tlb_generation; /* Overlap with serialization */
invlpg(smp_tlb_addr1);
- atomic_add_int(&smp_tlb_wait, 1);
+ PCPU_SET(smp_tlb_done, generation);
}
void
invlrng_handler(void)
{
- vm_offset_t addr;
+ vm_offset_t addr, addr2;
+ uint32_t generation;
#ifdef COUNT_XINVLTLB_HITS
xhits_rng[PCPU_GET(cpuid)]++;
@@ -1518,10 +1545,12 @@ invlrng_handler(void)
#endif /* COUNT_IPIS */
addr = smp_tlb_addr1;
+ addr2 = smp_tlb_addr2;
+ generation = smp_tlb_generation; /* Overlap with serialization */
do {
invlpg(addr);
addr += PAGE_SIZE;
- } while (addr < smp_tlb_addr2);
+ } while (addr < addr2);
- atomic_add_int(&smp_tlb_wait, 1);
+ PCPU_SET(smp_tlb_done, generation);
}
diff --git a/tests/sys/Makefile b/tests/sys/Makefile
index 944e820..682e21c 100644
--- a/tests/sys/Makefile
+++ b/tests/sys/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-TESTSDIR= ${TESTSBASE}/sys
+TESTSDIR= ${TESTSBASE}/sys
TESTS_SUBDIRS+= acl
TESTS_SUBDIRS+= aio
diff --git a/tests/sys/mac/bsdextended/matches_test.sh b/tests/sys/mac/bsdextended/matches_test.sh
index 11cac81..929bbca 100644
--- a/tests/sys/mac/bsdextended/matches_test.sh
+++ b/tests/sys/mac/bsdextended/matches_test.sh
@@ -36,6 +36,12 @@ if ! sysctl -N security.mac.bsdextended >/dev/null 2>&1; then
echo "1..0 # SKIP mac_bsdextended(4) support isn't available"
exit 0
fi
+if [ "$TMPDIR" != "/tmp" ]; then
+ if ! chmod -Rf 0755 $TMPDIR; then
+ echo "1..0 # SKIP failed to chmod $TMPDIR"
+ exit 0
+ fi
+fi
if ! playground=$(mktemp -d $TMPDIR/tmp.XXXXXXX); then
echo "1..0 # SKIP failed to create temporary directory"
exit 0
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 779b0ef..b21f32e 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -6059,6 +6059,13 @@ OLD_FILES+=usr/share/snmp/mibs/BEGEMOT-NETGRAPH.txt
.endif
.if ${MK_NIS} == no
+OLD_FILES+=etc/rc.d/ypbind
+OLD_FILES+=etc/rc.d/ypldap
+OLD_FILES+=etc/rc.d/yppasswdd
+OLD_FILES+=etc/rc.d/ypserv
+OLD_FILES+=etc/rc.d/ypset
+OLD_FILES+=etc/rc.d/ypupdated
+OLD_FILES+=etc/rc.d/ypxfrd
OLD_FILES+=usr/bin/ypcat
OLD_FILES+=usr/bin/ypchfn
OLD_FILES+=usr/bin/ypchpass
@@ -6800,7 +6807,6 @@ OLD_FILES+=usr/bin/rcsdiff
OLD_FILES+=usr/bin/rcsfreeze
OLD_FILES+=usr/bin/rcsmerge
OLD_FILES+=usr/bin/rlog
-OLD_FILES+=usr/sbin/etcupdate
OLD_FILES+=usr/share/man/man1/ci.1.gz
OLD_FILES+=usr/share/man/man1/co.1.gz
OLD_FILES+=usr/share/man/man1/merge.1.gz
@@ -6812,16 +6818,6 @@ OLD_FILES+=usr/share/man/man1/rcsintro.1.gz
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
diff --git a/usr.bin/bsdcat/Makefile b/usr.bin/bsdcat/Makefile
index 65099e5..c689ae4 100644
--- a/usr.bin/bsdcat/Makefile
+++ b/usr.bin/bsdcat/Makefile
@@ -6,7 +6,7 @@ _LIBARCHIVEDIR= ${.CURDIR}/../../contrib/libarchive
_LIBARCHIVECONFDIR= ${.CURDIR}/../../lib/libarchive
PROG= bsdcat
-BSDCAT_VERSION_STRING= 3.2.1
+BSDCAT_VERSION_STRING= 3.2.2
.PATH: ${_LIBARCHIVEDIR}/cat
SRCS= bsdcat.c cmdline.c
diff --git a/usr.bin/calendar/calendar.1 b/usr.bin/calendar/calendar.1
index 374fbef..570b187 100644
--- a/usr.bin/calendar/calendar.1
+++ b/usr.bin/calendar/calendar.1
@@ -28,7 +28,7 @@
.\" @(#)calendar.1 8.1 (Berkeley) 6/29/93
.\" $FreeBSD$
.\"
-.Dd April 6, 2013
+.Dd July 24, 2016
.Dt CALENDAR 1
.Os
.Sh NAME
@@ -295,7 +295,6 @@ This is no longer true, the date is only recognized when it occurs
at the beginning of a line.
.Sh SEE ALSO
.Xr at 1 ,
-.Xr cpp 1 ,
.Xr mail 1 ,
.Xr cron 8
.Sh HISTORY
diff --git a/usr.bin/calendar/io.c b/usr.bin/calendar/io.c
index 0a5dd85..a8c1efd 100644
--- a/usr.bin/calendar/io.c
+++ b/usr.bin/calendar/io.c
@@ -118,7 +118,7 @@ cal_fopen(const char *file)
return (NULL);
}
- for (i = 0; i < sizeof(calendarHomes)/sizeof(calendarHomes[0]) ; i++) {
+ for (i = 0; i < nitems(calendarHomes); i++) {
if (chdir(calendarHomes[i]) != 0)
continue;
diff --git a/usr.bin/cpio/Makefile b/usr.bin/cpio/Makefile
index 48043f6..6af6018 100644
--- a/usr.bin/cpio/Makefile
+++ b/usr.bin/cpio/Makefile
@@ -6,7 +6,7 @@ _LIBARCHIVEDIR= ${.CURDIR}/../../contrib/libarchive
_LIBARCHIVECONFDIR= ${.CURDIR}/../../lib/libarchive
PROG= bsdcpio
-BSDCPIO_VERSION_STRING= 3.2.1
+BSDCPIO_VERSION_STRING= 3.2.2
.PATH: ${_LIBARCHIVEDIR}/cpio
SRCS= cpio.c cmdline.c
diff --git a/usr.bin/elfdump/elfdump.c b/usr.bin/elfdump/elfdump.c
index e42727a..feb5ddd 100644
--- a/usr.bin/elfdump/elfdump.c
+++ b/usr.bin/elfdump/elfdump.c
@@ -240,9 +240,9 @@ d_tags(u_int64_t tag)
case 0x6ffffff0: return "DT_GNU_VERSYM";
/* 0x70000000 - 0x7fffffff processor-specific semantics */
case 0x70000000: return "DT_IA_64_PLT_RESERVE";
- case 0x7ffffffd: return "DT_SUNW_AUXILIARY";
- case 0x7ffffffe: return "DT_SUNW_USED";
- case 0x7fffffff: return "DT_SUNW_FILTER";
+ case DT_AUXILIARY: return "DT_AUXILIARY";
+ case DT_USED: return "DT_USED";
+ case DT_FILTER: return "DT_FILTER";
}
snprintf(unknown_tag, sizeof(unknown_tag),
"ERROR: TAG NOT DEFINED -- tag 0x%jx", (uintmax_t)tag);
diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c
index 6493688..6f617ee 100644
--- a/usr.bin/gcore/elfcore.c
+++ b/usr.bin/gcore/elfcore.c
@@ -586,6 +586,7 @@ elf_note_prpsinfo(void *arg, size_t *sizep)
} else
strlcpy(psinfo->pr_psargs, kip.ki_comm,
sizeof(psinfo->pr_psargs));
+ psinfo->pr_pid = pid;
*sizep = sizeof(*psinfo);
return (psinfo);
diff --git a/usr.bin/gzip/gzip.c b/usr.bin/gzip/gzip.c
index 8f22abc..4a649b8 100644
--- a/usr.bin/gzip/gzip.c
+++ b/usr.bin/gzip/gzip.c
@@ -155,7 +155,7 @@ static suffixes_t suffixes[] = {
#endif /* SMALL */
#undef SUFFIX
};
-#define NUM_SUFFIXES (sizeof suffixes / sizeof suffixes[0])
+#define NUM_SUFFIXES (nitems(suffixes))
#define SUFFIX_MAXLEN 30
static const char gzip_version[] = "FreeBSD gzip 20150413";
diff --git a/usr.bin/indent/indent.c b/usr.bin/indent/indent.c
index 3035faa..7c2cbea 100644
--- a/usr.bin/indent/indent.c
+++ b/usr.bin/indent/indent.c
@@ -1133,7 +1133,7 @@ check_type:
while ((c = getc(input)) == '\n');
ungetc(c, input);
}
- if ((size_t)ifdef_level < sizeof(state_stack)/sizeof(state_stack[0])) {
+ if ((size_t)ifdef_level < nitems(state_stack)) {
match_state[ifdef_level].tos = -1;
state_stack[ifdef_level++] = ps;
}
diff --git a/usr.bin/locale/locale.c b/usr.bin/locale/locale.c
index 8e1b03a..b295b17 100644
--- a/usr.bin/locale/locale.c
+++ b/usr.bin/locale/locale.c
@@ -220,10 +220,10 @@ struct _kwinfo {
"(POSIX legacy)" } /* compat */
};
-#define NKWINFO (sizeof(kwinfo)/sizeof(kwinfo[0]))
+#define NKWINFO (nitems(kwinfo))
const char *boguslocales[] = { "UTF-8" };
-#define NBOGUS (sizeof(boguslocales)/sizeof(boguslocales[0]))
+#define NBOGUS (nitems(boguslocales))
int
main(int argc, char *argv[])
diff --git a/usr.bin/localedef/collate.c b/usr.bin/localedef/collate.c
index 63dd4c7..7890538 100644
--- a/usr.bin/localedef/collate.c
+++ b/usr.bin/localedef/collate.c
@@ -490,7 +490,7 @@ define_collsym(char *name)
{
collsym_t *sym;
- if ((sym = calloc(sizeof (*sym), 1)) == NULL) {
+ if ((sym = calloc(1, sizeof(*sym))) == NULL) {
fprintf(stderr,"out of memory");
return;
}
@@ -536,7 +536,7 @@ get_collundef(char *name)
srch.name = name;
if ((ud = RB_FIND(collundefs, &collundefs, &srch)) == NULL) {
- if (((ud = calloc(sizeof (*ud), 1)) == NULL) ||
+ if (((ud = calloc(1, sizeof(*ud))) == NULL) ||
((ud->name = strdup(name)) == NULL)) {
fprintf(stderr,"out of memory");
free(ud);
@@ -561,7 +561,7 @@ get_collchar(wchar_t wc, int create)
srch.wc = wc;
cc = RB_FIND(collchars, &collchars, &srch);
if ((cc == NULL) && create) {
- if ((cc = calloc(sizeof (*cc), 1)) == NULL) {
+ if ((cc = calloc(1, sizeof(*cc))) == NULL) {
fprintf(stderr, "out of memory");
return (NULL);
}
@@ -793,7 +793,7 @@ define_collelem(char *name, wchar_t *wcs)
return;
}
- if ((e = calloc(sizeof (*e), 1)) == NULL) {
+ if ((e = calloc(1, sizeof(*e))) == NULL) {
fprintf(stderr, "out of memory");
return;
}
@@ -927,7 +927,7 @@ add_order_subst(void)
s = RB_FIND(substs_ref, &substs_ref[curr_weight], &srch);
if (s == NULL) {
- if ((s = calloc(sizeof (*s), 1)) == NULL) {
+ if ((s = calloc(1, sizeof(*s))) == NULL) {
fprintf(stderr,"out of memory");
return;
}
@@ -1035,7 +1035,7 @@ add_weight(int32_t ref, int pass)
if (RB_FIND(weights, &weights[pass], &srch) != NULL)
return;
- if ((w = calloc(sizeof (*w), 1)) == NULL) {
+ if ((w = calloc(1, sizeof(*w))) == NULL) {
fprintf(stderr, "out of memory");
return;
}
diff --git a/usr.bin/mkcsmapper/mkcsmapper.1 b/usr.bin/mkcsmapper/mkcsmapper.1
index 8faf5e6..ede990e 100644
--- a/usr.bin/mkcsmapper/mkcsmapper.1
+++ b/usr.bin/mkcsmapper/mkcsmapper.1
@@ -34,7 +34,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd Sep 6, 2009
+.Dd July 9, 2016
.Dt MKCSMAPPER 1
.Os
.Sh NAME
@@ -43,10 +43,10 @@
.Xr iconv 3
.Sh SYNOPSIS
.Nm
-.Op Fl mpd
-.Fl o
-.Ar outfile
-.Ar infile
+.Op Fl d
+.Op Fl m | Fl p
+.Op Fl o Ar outfile
+.Op Ar infile
.Sh DESCRIPTION
The
.Nm
@@ -60,7 +60,7 @@ A pivot file, which the possible source and destination encoding
pairs or the set of mappings to use for a compound encoding.
.Pp
The following options are available:
-.Bl -tag -width 0123
+.Bl -tag -width XoXoutfileXX
.It Fl d
Turns on debug mode.
.It Fl m
@@ -82,7 +82,8 @@ Generate pivot data from
.Sh HISTORY
.Nm
first appeared in
-.Nx 2.0 , and made its appearance in
+.Nx 2.0 ,
+and made its appearance in
.Fx 9.0 .
.Sh AUTHORS
This manual page was written by
diff --git a/usr.bin/mkcsmapper/yacc.y b/usr.bin/mkcsmapper/yacc.y
index 18497ce..97aade1 100644
--- a/usr.bin/mkcsmapper/yacc.y
+++ b/usr.bin/mkcsmapper/yacc.y
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $NetBSD: yacc.y,v 1.7 2006/09/09 14:35:17 tnozaki Exp $ */
+/* $NetBSD: yacc.y,v 1.11 2016/06/28 09:22:16 wiz Exp $ */
%{
/*-
@@ -664,18 +664,15 @@ do_mkpv(FILE *in)
if (ret && output)
unlink(output); /* dump failure */
if (ret)
- errx(EXIT_FAILURE, "%s\n", strerror(ret));
+ errc(EXIT_FAILURE, ret, "");
}
static void
usage(void)
{
- warnx("usage: \n"
- "\t%s [-d] [-o outfile] [infile]\n"
- "\t%s -m [-d] [-o outfile] [infile]\n"
- "\t%s -p [-d] [-o outfile] [infile]\n",
- getprogname(), getprogname(), getprogname());
- exit(1);
+ fprintf(stderr, "Usage: %s [-d] [-m|-p] [-o outfile] [infile]\n",
+ getprogname());
+ exit(EXIT_FAILURE);
}
int
diff --git a/usr.bin/netstat/pfkey.c b/usr.bin/netstat/pfkey.c
index 1a60b48..e12181b 100644
--- a/usr.bin/netstat/pfkey.c
+++ b/usr.bin/netstat/pfkey.c
@@ -101,8 +101,7 @@ static const char *pfkey_msgtype_names (int);
static const char *
pfkey_msgtype_names(int x)
{
- const int max =
- sizeof(pfkey_msgtypenames)/sizeof(pfkey_msgtypenames[0]);
+ const int max = nitems(pfkey_msgtypenames);
static char buf[20];
if (x < max && pfkey_msgtypenames[x])
diff --git a/usr.bin/printenv/printenv.c b/usr.bin/printenv/printenv.c
index 315833e..27882ab 100644
--- a/usr.bin/printenv/printenv.c
+++ b/usr.bin/printenv/printenv.c
@@ -83,8 +83,8 @@ main(int argc, char *argv[])
for (ep = environ; *ep; ep++)
if (!memcmp(*ep, *argv, len)) {
cp = *ep + len;
- if (!*cp || *cp == '=') {
- (void)printf("%s\n", *cp ? cp + 1 : cp);
+ if (*cp == '=') {
+ (void)printf("%s\n", cp + 1);
exit(0);
}
}
diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c
index ae7928d..1626697 100644
--- a/usr.bin/procstat/procstat_files.c
+++ b/usr.bin/procstat/procstat_files.c
@@ -235,8 +235,7 @@ static struct cap_desc {
{ CAP_SOCK_CLIENT, "scl" },
{ CAP_SOCK_SERVER, "ssr" },
};
-static const u_int cap_desc_count = sizeof(cap_desc) /
- sizeof(cap_desc[0]);
+static const u_int cap_desc_count = nitems(cap_desc);
static u_int
width_capability(cap_rights_t *rightsp)
diff --git a/usr.bin/rpcgen/rpc_main.c b/usr.bin/rpcgen/rpc_main.c
index 32e47a0..78bc610 100644
--- a/usr.bin/rpcgen/rpc_main.c
+++ b/usr.bin/rpcgen/rpc_main.c
@@ -82,11 +82,11 @@ static char pathbuf[MAXPATHLEN + 1];
static const char *allv[] = {
"rpcgen", "-s", "udp", "-s", "tcp",
};
-static int allc = sizeof (allv)/sizeof (allv[0]);
+static int allc = nitems(allv);
static const char *allnv[] = {
"rpcgen", "-s", "netpath",
};
-static int allnc = sizeof (allnv)/sizeof (allnv[0]);
+static int allnc = nitems(allnv);
/*
* machinations for handling expanding argument list
diff --git a/usr.bin/sdiff/Makefile b/usr.bin/sdiff/Makefile
index 504adc2..f4772cc 100644
--- a/usr.bin/sdiff/Makefile
+++ b/usr.bin/sdiff/Makefile
@@ -3,7 +3,7 @@
.include <src.opts.mk>
PROG= sdiff
-SRCS= common.c edit.c sdiff.c
+SRCS= edit.c sdiff.c
WARNS= 3
MAN1= sdiff.1
diff --git a/usr.bin/sdiff/common.c b/usr.bin/sdiff/common.c
deleted file mode 100644
index 686965c..0000000
--- a/usr.bin/sdiff/common.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/* $OpenBSD: common.c,v 1.4 2006/05/25 03:20:32 ray Exp $ */
-
-/*
- * Written by Raymond Lai <ray@cyth.net>.
- * Public domain.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <err.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "common.h"
-
-void
-cleanup(const char *filename)
-{
-
- if (unlink(filename))
- err(2, "could not delete: %s", filename);
- exit(2);
-}
diff --git a/usr.bin/sdiff/common.h b/usr.bin/sdiff/common.h
deleted file mode 100644
index 127c1f4..0000000
--- a/usr.bin/sdiff/common.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* $OpenBSD: common.h,v 1.2 2006/05/25 03:20:32 ray Exp $ */
-/* $FreeBSD$ */
-
-/*
- * Written by Raymond Lai <ray@cyth.net>.
- * Public domain.
- */
-
-void cleanup(const char *) __dead2;
diff --git a/usr.bin/sdiff/edit.c b/usr.bin/sdiff/edit.c
index 21f7cdc..993b515 100644
--- a/usr.bin/sdiff/edit.c
+++ b/usr.bin/sdiff/edit.c
@@ -21,10 +21,16 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-#include "common.h"
#include "extern.h"
-int editit(const char *);
+static void
+cleanup(const char *filename)
+{
+
+ if (unlink(filename))
+ err(2, "could not delete: %s", filename);
+ exit(2);
+}
/*
* Execute an editor on the specified pathname, which is interpreted
@@ -32,7 +38,7 @@ int editit(const char *);
*
* Returns -1 on error, or the exit value on success.
*/
-int
+static int
editit(const char *pathname)
{
sig_t sighup, sigint, sigquit, sigchld;
diff --git a/usr.bin/sdiff/sdiff.c b/usr.bin/sdiff/sdiff.c
index 008de53..34fcf7c 100644
--- a/usr.bin/sdiff/sdiff.c
+++ b/usr.bin/sdiff/sdiff.c
@@ -28,7 +28,6 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-#include "common.h"
#include "extern.h"
#define DIFF_PATH "/usr/bin/diff"
@@ -105,9 +104,6 @@ enum {
HLINES_OPT,
LFILES_OPT,
DIFFPROG_OPT,
- PIPE_FD,
- /* pid from the diff parent (if applicable) */
- DIFF_PID,
NOOP_OPT,
};
@@ -121,8 +117,6 @@ static struct option longopts[] = {
{ "output", required_argument, NULL, 'o' },
{ "diff-program", required_argument, NULL, DIFFPROG_OPT },
- { "pipe-fd", required_argument, NULL, PIPE_FD },
- { "diff-pid", required_argument, NULL, DIFF_PID },
/* Options processed by diff. */
{ "ignore-file-name-case", no_argument, NULL, FCASE_IGNORE_OPT },
{ "no-ignore-file-name-case", no_argument, NULL, FCASE_SENSITIVE_OPT },
@@ -144,24 +138,25 @@ static struct option longopts[] = {
};
static const char *help_msg[] = {
- "\nusage: sdiff [-abdilstW] [-I regexp] [-o outfile] [-w width] file1 file2\n",
- "\t-l, --left-column, Only print the left column for identical lines.",
- "\t-o OUTFILE, --output=OUTFILE, nteractively merge file1 and file2 into outfile.",
- "\t-s, --suppress-common-lines, Skip identical lines.",
- "\t-w WIDTH, --width=WIDTH, Print a maximum of WIDTH characters on each line.",
- "\tOptions passed to diff(1) are:",
- "\t\t-a, --text, Treat file1 and file2 as text files.",
- "\t\t-b, --ignore-trailing-cr, Ignore trailing blank spaces.",
- "\t\t-d, --minimal, Minimize diff size.",
- "\t\t-I RE, --ignore-matching-lines=RE, Ignore changes whose line matches RE.",
- "\t\t-i, --ignore-case, Do a case-insensitive comparison.",
- "\t\t-t, --expand-tabs Expand tabs to spaces.",
- "\t\t-W, --ignore-all-spaces, Ignore all spaces.",
- "\t\t--speed-large-files, Assume large file with scattered changes.",
- "\t\t--strip-trailing-cr, Strip trailing carriage return.",
- "\t\t--ignore-file-name-case, Ignore case of file names.",
- "\t\t--no-ignore-file-name-case, Do not ignore file name case",
- "\t\t--tabsize NUM, Change size of tabs (default 8.)",
+ "usage: sdiff [-abdilstW] [-I regexp] [-o outfile] [-w width] file1 file2\n",
+ "-l, --left-column: only print the left column for identical lines.",
+ "-o OUTFILE, --output=OUTFILE: interactively merge file1 and file2 into outfile.",
+ "-s, --suppress-common-lines: skip identical lines.",
+ "-w WIDTH, --width=WIDTH: print a maximum of WIDTH characters on each line.",
+ "",
+ "Options passed to diff(1) are:",
+ "\t-a, --text: treat file1 and file2 as text files.",
+ "\t-b, --ignore-trailing-cr: ignore trailing blank spaces.",
+ "\t-d, --minimal: minimize diff size.",
+ "\t-I RE, --ignore-matching-lines=RE: ignore changes whose line matches RE.",
+ "\t-i, --ignore-case: do a case-insensitive comparison.",
+ "\t-t, --expand-tabs: sxpand tabs to spaces.",
+ "\t-W, --ignore-all-spaces: ignore all spaces.",
+ "\t--speed-large-files: assume large file with scattered changes.",
+ "\t--strip-trailing-cr: strip trailing carriage return.",
+ "\t--ignore-file-name-case: ignore case of file names.",
+ "\t--no-ignore-file-name-case: do not ignore file name case",
+ "\t--tabsize NUM: change size of tabs (default 8.)",
NULL,
};
@@ -237,7 +232,7 @@ main(int argc, char **argv)
FILE *diffpipe=NULL, *file1, *file2;
size_t diffargc = 0, wflag = WIDTH;
int ch, fd[2] = {-1}, status;
- pid_t pid=0; pid_t ppid =-1;
+ pid_t pid=0;
const char *outfile = NULL;
struct option *popt;
char **diffargv, *diffprog = DIFF_PATH, *filename1, *filename2,
@@ -320,11 +315,6 @@ main(int argc, char **argv)
if (errstr)
errx(2, "width is %s: %s", errstr, optarg);
break;
- case DIFF_PID:
- ppid = strtonum(optarg, 0, INT_MAX, &errstr);
- if (errstr)
- errx(2, "diff pid value is %s: %s", errstr, optarg);
- break;
case HELP_OPT:
for (i = 0; help_msg[i] != NULL; i++)
printf("%s\n", help_msg[i]);
@@ -393,35 +383,34 @@ main(int argc, char **argv)
errx(2, "width is too large: %zu", width);
line_width = width * 2 + 3;
- if (ppid == -1 ) {
- if (pipe(fd))
- err(2, "pipe");
-
- switch (pid = fork()) {
- case 0:
- /* child */
- /* We don't read from the pipe. */
- close(fd[0]);
- if (dup2(fd[1], STDOUT_FILENO) == -1)
- err(2, "child could not duplicate descriptor");
- /* Free unused descriptor. */
- close(fd[1]);
- execvp(diffprog, diffargv);
- err(2, "could not execute diff: %s", diffprog);
- break;
- case -1:
- err(2, "could not fork");
- break;
- }
-
- /* parent */
- /* We don't write to the pipe. */
+ if (pipe(fd))
+ err(2, "pipe");
+
+ switch (pid = fork()) {
+ case 0:
+ /* child */
+ /* We don't read from the pipe. */
+ close(fd[0]);
+ if (dup2(fd[1], STDOUT_FILENO) == -1)
+ err(2, "child could not duplicate descriptor");
+ /* Free unused descriptor. */
close(fd[1]);
-
- /* Open pipe to diff command. */
- if ((diffpipe = fdopen(fd[0], "r")) == NULL)
- err(2, "could not open diff pipe");
+ execvp(diffprog, diffargv);
+ err(2, "could not execute diff: %s", diffprog);
+ break;
+ case -1:
+ err(2, "could not fork");
+ break;
}
+
+ /* parent */
+ /* We don't write to the pipe. */
+ close(fd[1]);
+
+ /* Open pipe to diff command. */
+ if ((diffpipe = fdopen(fd[0], "r")) == NULL)
+ err(2, "could not open diff pipe");
+
if ((file1 = fopen(filename1, "r")) == NULL)
err(2, "could not open %s", filename1);
if ((file2 = fopen(filename2, "r")) == NULL)
@@ -489,8 +478,8 @@ main(int argc, char **argv)
}
/*
- * When sdiff/zsdiff detects a binary file as input, executes them with
- * diff/zdiff to maintain the same behavior as GNU sdiff with binary input.
+ * When sdiff detects a binary file as input, executes them with
+ * diff to maintain the same behavior as GNU sdiff with binary input.
*/
static void
binexec(char *diffprog, char *f1, char *f2)
diff --git a/usr.bin/sed/tests/multi_test.sh b/usr.bin/sed/tests/multi_test.sh
index 66207a6..39e35c7 100644
--- a/usr.bin/sed/tests/multi_test.sh
+++ b/usr.bin/sed/tests/multi_test.sh
@@ -383,7 +383,6 @@ test_print()
mark '7.8'
echo line1 > lines3
echo "" >> lines3
- TODO=1
$SED -n -e '$p' lines3 /dev/null
}
diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c
index 4c55ff4..74195f6 100644
--- a/usr.bin/systat/main.c
+++ b/usr.bin/systat/main.c
@@ -261,7 +261,7 @@ display(void)
int i, j;
/* Get the load average over the last minute. */
- (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
+ (void) getloadavg(avenrun, nitems(avenrun));
(*curcmd->c_fetch)();
if (curcmd->c_flags & CF_LOADAV) {
j = 5.0*avenrun[0] + 0.5;
@@ -293,7 +293,7 @@ display(void)
GETSYSCTL("kstat.zfs.misc.arcstats.l2_hdr_size", arc[5]);
GETSYSCTL("kstat.zfs.misc.arcstats.other_size", arc[6]);
wmove(wload, 0, 0); wclrtoeol(wload);
- for (i = 0 ; i < sizeof(arc) / sizeof(arc[0]) ; i++) {
+ for (i = 0 ; i < nitems(arc); i++) {
if (arc[i] > 10llu * 1024 * 1024 * 1024 ) {
wprintw(wload, "%7lluG", arc[i] >> 30);
}
@@ -318,7 +318,7 @@ void
load(void)
{
- (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0]));
+ (void) getloadavg(avenrun, nitems(avenrun));
mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f",
avenrun[0], avenrun[1], avenrun[2]);
clrtoeol();
diff --git a/usr.bin/tar/Makefile b/usr.bin/tar/Makefile
index 0c9fafa..83bf195 100644
--- a/usr.bin/tar/Makefile
+++ b/usr.bin/tar/Makefile
@@ -4,7 +4,7 @@
_LIBARCHIVEDIR= ${.CURDIR}/../../contrib/libarchive
PROG= bsdtar
-BSDTAR_VERSION_STRING= 3.2.1
+BSDTAR_VERSION_STRING= 3.2.2
.PATH: ${_LIBARCHIVEDIR}/tar
SRCS= bsdtar.c \
diff --git a/usr.bin/tee/tee.c b/usr.bin/tee/tee.c
index 6b5c00c..302bb97 100644
--- a/usr.bin/tee/tee.c
+++ b/usr.bin/tee/tee.c
@@ -41,14 +41,18 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
-#include <sys/types.h>
+#include <sys/capsicum.h>
#include <sys/stat.h>
+#include <sys/types.h>
+
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
#include <unistd.h>
typedef struct _list {
@@ -69,6 +73,8 @@ main(int argc, char *argv[])
char *bp;
int append, ch, exitval;
char *buf;
+ cap_rights_t rights;
+ unsigned long cmd;
#define BSIZE (8 * 1024)
append = 0;
@@ -90,6 +96,16 @@ main(int argc, char *argv[])
if ((buf = malloc(BSIZE)) == NULL)
err(1, "malloc");
+ cap_rights_init(&rights, CAP_READ, CAP_FSTAT);
+ if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
+ err(EXIT_FAILURE, "unable to limit rights for stdin");
+ cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT, CAP_IOCTL);
+ if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
+ err(EXIT_FAILURE, "unable to limit rights for stderr");
+ cmd = TIOCGETA;
+ if (cap_ioctls_limit(STDERR_FILENO, &cmd, 1) < 0 && errno != ENOSYS)
+ err(EXIT_FAILURE, "unable to limit ioctls for stderr");
+
add(STDOUT_FILENO, "stdout");
for (exitval = 0; *argv; ++argv)
@@ -100,6 +116,8 @@ main(int argc, char *argv[])
} else
add(fd, *argv);
+ if (cap_enter() < 0 && errno != ENOSYS)
+ err(EXIT_FAILURE, "unable to enter capability mode");
while ((rval = read(STDIN_FILENO, buf, BSIZE)) > 0)
for (p = head; p; p = p->next) {
n = rval;
@@ -129,6 +147,21 @@ static void
add(int fd, const char *name)
{
LIST *p;
+ cap_rights_t rights;
+ unsigned long cmd;
+
+ if (fd == STDOUT_FILENO)
+ cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT, CAP_IOCTL);
+ else
+ cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT);
+ if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS)
+ err(EXIT_FAILURE, "unable to limit rights");
+
+ if (fd == STDOUT_FILENO) {
+ cmd = TIOCGETA;
+ if (cap_ioctls_limit(fd, &cmd, 1) < 0 && errno != ENOSYS)
+ err(EXIT_FAILURE, "unable to limit ioctls for stdout");
+ }
if ((p = malloc(sizeof(LIST))) == NULL)
err(1, "malloc");
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
index 92cd7c5..e6ceb92 100644
--- a/usr.bin/top/machine.c
+++ b/usr.bin/top/machine.c
@@ -69,7 +69,9 @@ static int namelength = 8;
#endif
/* TOP_JID_LEN based on max of 999999 */
#define TOP_JID_LEN 7
+#define TOP_SWAP_LEN 6
static int jidlength;
+static int swaplength;
static int cmdlengthdelta;
/* Prototypes for top internals */
@@ -111,20 +113,20 @@ static char io_header[] =
"%5d%*s %-*.*s %6ld %6ld %6ld %6ld %6ld %6ld %6.2f%% %.*s"
static char smp_header_thr[] =
- " PID%*s %-*.*s THR PRI NICE SIZE RES STATE C TIME %7s COMMAND";
+ " PID%*s %-*.*s THR PRI NICE SIZE RES%*s STATE C TIME %7s COMMAND";
static char smp_header[] =
- " PID%*s %-*.*s " "PRI NICE SIZE RES STATE C TIME %7s COMMAND";
+ " PID%*s %-*.*s " "PRI NICE SIZE RES%*s STATE C TIME %7s COMMAND";
#define smp_Proc_format \
- "%5d%*s %-*.*s %s%3d %4s%7s %6s %-6.6s %2d%7s %6.2f%% %.*s"
+ "%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s %2d%7s %6.2f%% %.*s"
static char up_header_thr[] =
- " PID%*s %-*.*s THR PRI NICE SIZE RES STATE TIME %7s COMMAND";
+ " PID%*s %-*.*s THR PRI NICE SIZE RES%*s STATE TIME %7s COMMAND";
static char up_header[] =
- " PID%*s %-*.*s " "PRI NICE SIZE RES STATE TIME %7s COMMAND";
+ " PID%*s %-*.*s " "PRI NICE SIZE RES%*s STATE TIME %7s COMMAND";
#define up_Proc_format \
- "%5d%*s %-*.*s %s%3d %4s%7s %6s %-6.6s%.0d%7s %6.2f%% %.*s"
+ "%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s%.0d%7s %6.2f%% %.*s"
/* process state names for the "STATE" column of the display */
@@ -227,6 +229,10 @@ static int pageshift; /* log base 2 of the pagesize */
#define pagetok(size) ((size) << pageshift)
+/* swap usage */
+#define ki_swap(kip) \
+ ((kip)->ki_swrss > (kip)->ki_rssize ? (kip)->ki_swrss - (kip)->ki_rssize : 0)
+
/* useful externals */
long percentages();
@@ -237,7 +243,7 @@ long percentages();
char *ordernames[] = {
"cpu", "size", "res", "time", "pri", "threads",
"total", "read", "write", "fault", "vcsw", "ivcsw",
- "jid", "pid", NULL
+ "jid", "swap", "pid", NULL
};
#endif
@@ -252,6 +258,7 @@ static long *pcpu_cp_old;
static long *pcpu_cp_diff;
static int *pcpu_cpu_states;
+static int compare_swap(const void *a, const void *b);
static int compare_jid(const void *a, const void *b);
static int compare_pid(const void *a, const void *b);
static int compare_tid(const void *a, const void *b);
@@ -412,6 +419,11 @@ format_header(char *uname_field)
else
jidlength = 0;
+ if (ps.swap)
+ swaplength = TOP_SWAP_LEN + 1; /* +1 for extra left space */
+ else
+ swaplength = 0;
+
switch (displaymode) {
case DISP_CPU:
/*
@@ -426,6 +438,7 @@ format_header(char *uname_field)
snprintf(Header, sizeof(Header), prehead,
jidlength, ps.jail ? " JID" : "",
namelength, namelength, uname_field,
+ swaplength, ps.swap ? " SWAP" : "",
ps.wcpu ? "WCPU" : "CPU");
break;
case DISP_IO:
@@ -902,7 +915,8 @@ format_next_process(caddr_t handle, char *(*get_userid)(int), int flags)
int cpu, state;
struct rusage ru, *rup;
long p_tot, s_tot;
- char *proc_fmt, thr_buf[6], jid_buf[TOP_JID_LEN + 1];
+ char *proc_fmt, thr_buf[6];
+ char jid_buf[TOP_JID_LEN + 1], swap_buf[TOP_SWAP_LEN + 1];
char *cmdbuf = NULL;
char **args;
const int cmdlen = 128;
@@ -1061,6 +1075,13 @@ format_next_process(caddr_t handle, char *(*get_userid)(int), int flags)
snprintf(jid_buf, sizeof(jid_buf), "%*d",
jidlength - 1, pp->ki_jid);
+ if (ps.swap == 0)
+ swap_buf[0] = '\0';
+ else
+ snprintf(swap_buf, sizeof(swap_buf), "%*s",
+ swaplength - 1,
+ format_k2(pagetok(ki_swap(pp)))); /* XXX */
+
if (displaymode == DISP_IO) {
oldp = get_old_proc(pp);
if (oldp != NULL) {
@@ -1122,6 +1143,7 @@ format_next_process(caddr_t handle, char *(*get_userid)(int), int flags)
format_nice(pp),
format_k2(PROCSIZE(pp)),
format_k2(pagetok(pp->ki_rssize)),
+ swaplength, swaplength, swap_buf,
status,
cpu,
format_time(cputime),
@@ -1309,6 +1331,12 @@ static int sorted_state[] = {
return (diff > 0 ? 1 : -1); \
} while (0)
+#define ORDERKEY_SWAP(a, b) do { \
+ int diff = (int)ki_swap(b) - (int)ki_swap(a); \
+ if (diff != 0) \
+ return (diff > 0 ? 1 : -1); \
+} while (0)
+
/* compare_cpu - the comparison function for sorting by cpu percentage */
int
@@ -1357,6 +1385,7 @@ int (*compares[])() = {
compare_vcsw,
compare_ivcsw,
compare_jid,
+ compare_swap,
NULL
};
@@ -1467,6 +1496,24 @@ compare_jid(const void *arg1, const void *arg2)
return (0);
}
+
+/* compare_swap - the comparison function for sorting by swap */
+static int
+compare_swap(const void *arg1, const void *arg2)
+{
+ struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
+ struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
+
+ ORDERKEY_SWAP(p1, p2);
+ ORDERKEY_PCTCPU(p1, p2);
+ ORDERKEY_CPTICKS(p1, p2);
+ ORDERKEY_STATE(p1, p2);
+ ORDERKEY_PRIO(p1, p2);
+ ORDERKEY_RSSIZE(p1, p2);
+ ORDERKEY_MEM(p1, p2);
+
+ return (0);
+}
#endif /* ORDER */
/* assorted comparison functions for sorting by i/o */
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index c2b0b7c..67499a1 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -25,6 +25,7 @@ SUBDIR= adduser \
digictl \
diskinfo \
dumpcis \
+ etcupdate \
extattr \
extattrctl \
fifolog \
@@ -188,7 +189,6 @@ SUBDIR.${MK_QUOTAS}+= edquota
SUBDIR.${MK_QUOTAS}+= quotaon
SUBDIR.${MK_QUOTAS}+= repquota
SUBDIR.${MK_RCMDS}+= rwhod
-SUBDIR.${MK_RCS}+= etcupdate
SUBDIR.${MK_SENDMAIL}+= editmap
SUBDIR.${MK_SENDMAIL}+= mailstats
SUBDIR.${MK_SENDMAIL}+= makemap
diff --git a/usr.sbin/bhyve/dbgport.c b/usr.sbin/bhyve/dbgport.c
index 5be0ceb..1421402 100644
--- a/usr.sbin/bhyve/dbgport.c
+++ b/usr.sbin/bhyve/dbgport.c
@@ -73,10 +73,8 @@ again:
printf("Waiting for connection from gdb\r\n");
printonce = 1;
}
- conn_fd = accept(listen_fd, NULL, NULL);
- if (conn_fd >= 0)
- fcntl(conn_fd, F_SETFL, O_NONBLOCK);
- else if (errno != EINTR)
+ conn_fd = accept4(listen_fd, NULL, NULL, SOCK_NONBLOCK);
+ if (conn_fd < 0 && errno != EINTR)
perror("accept");
}
diff --git a/usr.sbin/bhyve/vga.c b/usr.sbin/bhyve/vga.c
index 208064b..57dc26e 100644
--- a/usr.sbin/bhyve/vga.c
+++ b/usr.sbin/bhyve/vga.c
@@ -161,10 +161,10 @@ struct vga_softc {
*/
struct {
uint8_t dac_state;
- int dac_rd_index;
- int dac_rd_subindex;
- int dac_wr_index;
- int dac_wr_subindex;
+ uint8_t dac_rd_index;
+ uint8_t dac_rd_subindex;
+ uint8_t dac_wr_index;
+ uint8_t dac_wr_subindex;
uint8_t dac_palette[3 * 256];
uint32_t dac_palette_rgb[256];
} vga_dac;
diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8
index f034240..1271ed2 100644
--- a/usr.sbin/ctladm/ctladm.8
+++ b/usr.sbin/ctladm/ctladm.8
@@ -35,7 +35,7 @@
.\" $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.8#3 $
.\" $FreeBSD$
.\"
-.Dd September 26, 2015
+.Dd October 15, 2016
.Dt CTLADM 8
.Os
.Sh NAME
@@ -903,8 +903,21 @@ Specifies medium rotation rate of the device: 0 -- not reported,
.It Va formfactor
Specifies nominal form factor of the device: 0 -- not reported, 1 -- 5.25",
2 -- 3.5", 3 -- 2.5", 4 -- 1.8", 5 -- less then 1.8".
+.It Va provisioning_type
+When UNMAP support is enabled, this option specifies provisioning type:
+"resource", "thin" or "unknown".
+Default value is "thin".
+Logical units without UNMAP support are reported as fully provisioned.
.It Va unmap
-Set to "on", enables UNMAP support for the LUN, if supported by the backend.
+Setting to "on" or "off" controls UNMAP support for the logical unit.
+Default value is "on" if supported by the backend.
+.It Va unmap_max_lba
+.It Va unmap_max_descr
+Specify maximum allowed number of LBAs and block descriptors per UNMAP
+command to report in Block Limits VPD page.
+.It Va write_same_max_lba
+Specify maximum allowed number of LBAs per WRITE SAME command to report
+in Block Limits VPD page.
.It Va avail-threshold
.It Va used-threshold
.It Va pool-avail-threshold
diff --git a/usr.sbin/ctld/chap.c b/usr.sbin/ctld/chap.c
index 2120350..bf61f05 100644
--- a/usr.sbin/ctld/chap.c
+++ b/usr.sbin/ctld/chap.c
@@ -232,7 +232,7 @@ chap_new(void)
{
struct chap *chap;
- chap = calloc(sizeof(*chap), 1);
+ chap = calloc(1, sizeof(*chap));
if (chap == NULL)
log_err(1, "calloc");
@@ -333,7 +333,7 @@ rchap_new(const char *secret)
{
struct rchap *rchap;
- rchap = calloc(sizeof(*rchap), 1);
+ rchap = calloc(1, sizeof(*rchap));
if (rchap == NULL)
log_err(1, "calloc");
diff --git a/usr.sbin/ctld/keys.c b/usr.sbin/ctld/keys.c
index c2f1604..a3b12f0 100644
--- a/usr.sbin/ctld/keys.c
+++ b/usr.sbin/ctld/keys.c
@@ -43,7 +43,7 @@ keys_new(void)
{
struct keys *keys;
- keys = calloc(sizeof(*keys), 1);
+ keys = calloc(1, sizeof(*keys));
if (keys == NULL)
log_err(1, "calloc");
diff --git a/usr.sbin/ctld/pdu.c b/usr.sbin/ctld/pdu.c
index be3598e..2d4fcc6 100644
--- a/usr.sbin/ctld/pdu.c
+++ b/usr.sbin/ctld/pdu.c
@@ -81,11 +81,11 @@ pdu_new(struct connection *conn)
{
struct pdu *pdu;
- pdu = calloc(sizeof(*pdu), 1);
+ pdu = calloc(1, sizeof(*pdu));
if (pdu == NULL)
log_err(1, "calloc");
- pdu->pdu_bhs = calloc(sizeof(*pdu->pdu_bhs), 1);
+ pdu->pdu_bhs = calloc(1, sizeof(*pdu->pdu_bhs));
if (pdu->pdu_bhs == NULL)
log_err(1, "calloc");
diff --git a/usr.sbin/etcupdate/etcupdate.sh b/usr.sbin/etcupdate/etcupdate.sh
index bb12d36..2b4c145 100755
--- a/usr.sbin/etcupdate/etcupdate.sh
+++ b/usr.sbin/etcupdate/etcupdate.sh
@@ -814,15 +814,19 @@ merge_file()
local res
# Try the merge to see if there is a conflict.
- merge -q -p ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1 >/dev/null 2>&3
+ diff3 -E -m ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1 > /dev/null 2>&3
res=$?
case $res in
0)
# No conflicts, so just redo the merge to the
# real file.
- log "merge ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1"
+ log "diff3 -E -m ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1"
if [ -z "$dryrun" ]; then
- merge ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1
+ temp=$(mktemp -t etcupdate)
+ diff3 -E -m ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1 > ${temp}
+ # Use "cat >" to preserve metadata.
+ cat ${temp} > ${DESTDIR}$1
+ rm -f ${temp}
fi
post_install_file $1
echo " M $1"
@@ -832,10 +836,10 @@ merge_file()
# the conflicts directory.
if [ -z "$dryrun" ]; then
install_dirs $NEWTREE $CONFLICTS $1
- log "cp -Rp ${DESTDIR}$1 ${CONFLICTS}$1"
- cp -Rp ${DESTDIR}$1 ${CONFLICTS}$1 >&3 2>&1
- merge -A -q -L "yours" -L "original" -L "new" \
- ${CONFLICTS}$1 ${OLDTREE}$1 ${NEWTREE}$1
+ log "diff3 -m -A ${DESTDIR}$1 ${CONFLICTS}$1"
+ diff3 -m -A -L "yours" -L "original" -L "new" \
+ ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1 > \
+ ${CONFLICTS}$1
fi
echo " C $1"
;;
diff --git a/usr.sbin/fifolog/lib/fifolog_int.c b/usr.sbin/fifolog/lib/fifolog_int.c
index 9d3b437..f8aabdc 100644
--- a/usr.sbin/fifolog/lib/fifolog_int.c
+++ b/usr.sbin/fifolog/lib/fifolog_int.c
@@ -125,7 +125,7 @@ fifolog_int_open_i(struct fifolog_file *f, const char *fname, int mode)
/* Initialize zlib handling */
- f->zs = calloc(sizeof *f->zs, 1);
+ f->zs = calloc(1, sizeof(*f->zs));
if (f->zs == NULL)
return ("cannot malloc");
diff --git a/usr.sbin/fifolog/lib/fifolog_reader.c b/usr.sbin/fifolog/lib/fifolog_reader.c
index 0dda672..e771f88 100644
--- a/usr.sbin/fifolog/lib/fifolog_reader.c
+++ b/usr.sbin/fifolog/lib/fifolog_reader.c
@@ -59,7 +59,7 @@ fifolog_reader_open(const char *fname)
struct fifolog_reader *fr;
int i;
- fr = calloc(sizeof *fr, 1);
+ fr = calloc(1, sizeof(*fr));
if (fr == NULL)
err(1, "Cannot malloc");
diff --git a/usr.sbin/iscsid/chap.c b/usr.sbin/iscsid/chap.c
index 30c1cd4..f6b51d7 100644
--- a/usr.sbin/iscsid/chap.c
+++ b/usr.sbin/iscsid/chap.c
@@ -232,7 +232,7 @@ chap_new(void)
{
struct chap *chap;
- chap = calloc(sizeof(*chap), 1);
+ chap = calloc(1, sizeof(*chap));
if (chap == NULL)
log_err(1, "calloc");
@@ -333,7 +333,7 @@ rchap_new(const char *secret)
{
struct rchap *rchap;
- rchap = calloc(sizeof(*rchap), 1);
+ rchap = calloc(1, sizeof(*rchap));
if (rchap == NULL)
log_err(1, "calloc");
diff --git a/usr.sbin/iscsid/keys.c b/usr.sbin/iscsid/keys.c
index 8ac4788..4126bee 100644
--- a/usr.sbin/iscsid/keys.c
+++ b/usr.sbin/iscsid/keys.c
@@ -43,7 +43,7 @@ keys_new(void)
{
struct keys *keys;
- keys = calloc(sizeof(*keys), 1);
+ keys = calloc(1, sizeof(*keys));
if (keys == NULL)
log_err(1, "calloc");
diff --git a/usr.sbin/iscsid/pdu.c b/usr.sbin/iscsid/pdu.c
index 78aa065..4222446 100644
--- a/usr.sbin/iscsid/pdu.c
+++ b/usr.sbin/iscsid/pdu.c
@@ -81,11 +81,11 @@ pdu_new(struct connection *conn)
{
struct pdu *pdu;
- pdu = calloc(sizeof(*pdu), 1);
+ pdu = calloc(1, sizeof(*pdu));
if (pdu == NULL)
log_err(1, "calloc");
- pdu->pdu_bhs = calloc(sizeof(*pdu->pdu_bhs), 1);
+ pdu->pdu_bhs = calloc(1, sizeof(*pdu->pdu_bhs));
if (pdu->pdu_bhs == NULL)
log_err(1, "calloc");
diff --git a/usr.sbin/pciconf/pciconf.c b/usr.sbin/pciconf/pciconf.c
index d62ce77..1bc5526 100644
--- a/usr.sbin/pciconf/pciconf.c
+++ b/usr.sbin/pciconf/pciconf.c
@@ -697,6 +697,9 @@ static struct
{PCIC_CRYPTO, PCIS_CRYPTO_NETCOMP, "entertainment crypto"},
{PCIC_DASP, -1, "dasp"},
{PCIC_DASP, PCIS_DASP_DPIO, "DPIO module"},
+ {PCIC_DASP, PCIS_DASP_PERFCNTRS, "performance counters"},
+ {PCIC_DASP, PCIS_DASP_COMM_SYNC, "communication synchronizer"},
+ {PCIC_DASP, PCIS_DASP_MGMT_CARD, "signal processing management"},
{0, 0, NULL}
};
diff --git a/usr.sbin/pmcstat/pmcstat_log.h b/usr.sbin/pmcstat/pmcstat_log.h
index b4ced4d..32a22f4 100644
--- a/usr.sbin/pmcstat/pmcstat_log.h
+++ b/usr.sbin/pmcstat/pmcstat_log.h
@@ -76,7 +76,6 @@ enum pmcstat_image_type {
struct pmcstat_image {
LIST_ENTRY(pmcstat_image) pi_next; /* hash link */
- TAILQ_ENTRY(pmcstat_image) pi_lru; /* LRU list */
pmcstat_interned_string pi_execpath; /* cookie */
pmcstat_interned_string pi_samplename; /* sample path name */
pmcstat_interned_string pi_fullpath; /* path to FS object */
diff --git a/usr.sbin/rtsold/rtsol.c b/usr.sbin/rtsold/rtsol.c
index ced0a73..d40f243 100644
--- a/usr.sbin/rtsold/rtsol.c
+++ b/usr.sbin/rtsold/rtsol.c
@@ -347,7 +347,7 @@ rtsol_input(int s)
/* xxx: more validation? */
if ((ifi = find_ifinfo(pi->ipi6_ifindex)) == NULL) {
- warnmsg(LOG_INFO, __func__,
+ warnmsg(LOG_DEBUG, __func__,
"received RA from %s on an unexpected IF(%s)",
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
sizeof(ntopbuf)),
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
index a1fb217..a93336a 100644
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -634,10 +634,7 @@ main(int argc, char *argv[])
dprintf("sending on inet and/or inet6 socket\n");
}
- if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) >= 0)
- if (fcntl(fklog, F_SETFL, O_NONBLOCK) < 0)
- fklog = -1;
- if (fklog < 0)
+ if ((fklog = open(_PATH_KLOG, O_RDONLY|O_NONBLOCK, 0)) < 0)
dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
/* tuck my process id away */
diff --git a/usr.sbin/unbound/checkconf/Makefile b/usr.sbin/unbound/checkconf/Makefile
index 98ac3bb..e63be80 100644
--- a/usr.sbin/unbound/checkconf/Makefile
+++ b/usr.sbin/unbound/checkconf/Makefile
@@ -4,10 +4,10 @@
LDNSDIR= ${.CURDIR}/../../../contrib/ldns
UNBOUNDDIR= ${.CURDIR}/../../../contrib/unbound
-.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/smallapp ${UNBOUNDDIR}/doc
+.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/smallapp ${UNBOUNDDIR}/util ${UNBOUNDDIR}/doc
PROG= unbound-checkconf
-SRCS= unbound-checkconf.c worker_cb.c
+SRCS= ub_event.c unbound-checkconf.c worker_cb.c
CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR}
LIBADD= unbound pthread
MAN= unbound-checkconf.8
diff --git a/usr.sbin/unbound/control/Makefile b/usr.sbin/unbound/control/Makefile
index 9aab04a..928c7e9 100644
--- a/usr.sbin/unbound/control/Makefile
+++ b/usr.sbin/unbound/control/Makefile
@@ -4,10 +4,10 @@
LDNSDIR= ${.CURDIR}/../../../contrib/ldns
UNBOUNDDIR= ${.CURDIR}/../../../contrib/unbound
-.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/smallapp ${UNBOUNDDIR}/doc
+.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/smallapp ${UNBOUNDDIR}/util ${UNBOUNDDIR}/doc
PROG= unbound-control
-SRCS= unbound-control.c worker_cb.c
+SRCS= ub_event.c unbound-control.c worker_cb.c
CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR}
LIBADD= unbound crypto ssl pthread
MAN= unbound-control.8
diff --git a/usr.sbin/unbound/daemon/Makefile b/usr.sbin/unbound/daemon/Makefile
index af42975..fb614fa 100644
--- a/usr.sbin/unbound/daemon/Makefile
+++ b/usr.sbin/unbound/daemon/Makefile
@@ -4,10 +4,11 @@
LDNSDIR= ${.CURDIR}/../../../contrib/ldns
UNBOUNDDIR= ${.CURDIR}/../../../contrib/unbound
-.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/daemon ${UNBOUNDDIR}/doc
+.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/daemon ${UNBOUNDDIR}/util ${UNBOUNDDIR}/doc
PROG= unbound
-SRCS= acl_list.c cachedump.c daemon.c remote.c stats.c unbound.c worker.c
+SRCS= acl_list.c cachedump.c daemon.c remote.c stats.c ub_event.c \
+ unbound.c worker.c
CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR}
LIBADD= unbound util ssl crypto pthread
MAN= unbound.8 unbound.conf.5
OpenPOWER on IntegriCloud